• R/O
  • HTTP
  • SSH
  • HTTPS

Repository summary

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

C++ベースのLightweightなHTTPサーバー


Recent Commits RSS

Rev. Time Author Message
ca54241 2013-11-26 00:14:12 Michio Hirai master [BugFix] Forgot to add dtor code (where it has to have a ...
94c5015 2013-11-26 00:11:44 Michio Hirai [Function] First addition of http HttpSocketManager class...
8fbd88f 2013-11-23 22:55:50 Michio Hirai [Function] Change cm::IOVectorChain class template implem...
21a0a6e 2013-11-22 18:50:37 Michio Hirai [Refactor] Change a way to wait for an appropriate thread...
fa67399 2013-11-22 18:32:22 Michio Hirai [Function] New addition of cm::Condition class
a7815c9 2013-11-19 00:47:31 Michio Hirai [BugFix] Fix some compilation issues in Linux port and al...
4204b59 2013-11-18 02:19:45 Michio Hirai [Refactor] Change some README text.
6ca1a69 2013-11-18 02:16:01 Michio Hirai [Function] New support of no arugument type message handl...
a9d9e70 2013-11-17 19:32:01 Michio Hirai [Function] Change cm::Mutex implementation to support rec...
d4dd7af 2013-11-17 19:30:50 Michio Hirai [Refactor] Change unit test implementation (from memcpy t...

Branches

Name Rev. Time Author Message
master ca54241 2013-11-26 00:14:12 Michio Hirai [BugFix] Forgot to add dtor...

README.txt

============================================================
 FlyingHttpServer - lightweight HTTP server based on C++
------------------------------------------------------------
                                               by smg_ykz
============================================================

1. Introduction

This software is intended to be a lightweight C++ based HTTP server.
Although there are number of open-source based HTTP server softwares available,
what this software is trying to address is the following.

(a) By making use of the OOP design and generic/meta- programming techniques/idioms,
 it tries to keep the software some sort of extensible, and yet easy-to-maintain.

(b) It tries to be of help in case some embedded device has to deploy HTTP server.
 So in this sense, conventional CGI support which may be useful for scripting language
 such as Perl, Python, Ruby etc. should be some low priority.

(c) It tries to help programmers who are involved in this software get some hints on
 their daily programming.

2. Dependency

In order to keep the software good quality, it is essential that the software don't have
pretty much dependency on the other software components. The following are software
components which are identified as essential.

(a) CMake - http://www.cmake.org
 This is the build system we are going to use.

(b) Googlemock - http://code.google.com/p/googlemock/
 For the purpose of performing unit testing, we use this mocking framework. This software
 component also includes Googletest.

3. How to proceed with the things

Quality over Time - based on this belief, we are (perhaps only I'm...?) supposed to develop
this software. That indicates that the project will be slowly kept on going, which might not
attract users... Excuse me, in advance.

We are going to maintain the source code tree so that this software can be built succesfully
by multiple comipler collections. The followings are the compilation collections which are
being used for the build.

GNU GCC (running under MAC OS X)
 i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.1.00)
CLANG (running under MAC OS X)
 Apple clang version 3.0 (tags/Apple/clang-211.12) (based on LLVM 3.0svn)
 Target: x86_64-apple-darwin11.4.2
 Thread model: posix 
GNU GCC (running under CentOS 5.0)
 gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-50)
GNU GCC44 (running under CentOS 5.0)
 gcc44 (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3)

Before going into the very HTTP server development, firstly we are going to develop and/or
maintain the framework component, which should help the software some sort of good quality
etc.

4. (Sub-)Packages

In this softeware, packages are explicitly divided into different namespaces. The following
briefly shows what kind of packages are there in the software.

=======================================================================================================
[mt] -> Meta-programming library

This is the software package mainly focuses on providing meta/generic-programming components.
In that sense, almost all of them should be in the form of header files so that client code
can instantiate the module along with its parameterized type.

Basically I like to use so-called Typelist very much whose idea was elaborated in the authoritative
book named as 'Modern C++ Design - by Andrei Alexandrescu'. See how we can manipulate 'type' in
compilation time in the unit test code 'inc/test/mt_typelist_test.cpp'. (TODO:
put some more unit tests there)

[File inc/mt_static_assert.h]
This gives you the way to express a compile time assertion. You will be able to simply write a statement something like this.

STATIC_ASSERT(statement_which_is_true_in_compilation_time);

[File inc/mt_array_length.h]
This gives you the simple way to count number of elements in an array. Assume that we have the following
statement,

char_t buffer[128];

then the ARRAY_LENGTH macro should return 128. Since this will simply use compile time calculation,
there is no conputation const in run-time.

STATIC_ASSERT(ARRAY_LENGTH(buffer) == 128);

[File mt_auto_ptr.h]
This gives you std::auto_ptr equivalent. The reason why we don't use std::auto_ptr is that it has the following issues.

 1) std::auto_ptr doesn't incorporate 'checked delete' idiom. Depending on the way to write code, it may have a chance that the parameterized type to put into the std::auto_ptr is forward-declared without having the exact declaration. In such case, the std::auto_ptr may have quite subtle issue that is difficult to identify. In order to avoid such issue, we use this mt::AutoPtr class template instead of std::auto_ptr.

 2) reset() and set() member function. The std::auto_ptr class template has reset() member function that will be used for the purpose of releasing the object and also for the purpose of setting the new object. This nature sometimes introduces subtle issue in case that the class design of the paramterized type doesn't allow multiple objects to be present at the same time.

 std::auto_ptr<Type> obj(new Type);
 obj.reset(new Type); // This statement allow the originall Type object and another Type object to be present in a short period of time....

 In order to avoid such issue, mt::AutoPtr class template distinguish these 2 operations into multiple member methods of reset() and set(). In order to release the object, release() member method should be used and this should not be used for the purpose of putting another object. For the latter purpose, the other member method set() is to be used.

[File mt_mpl.h]
This gives you basic set of meta-programming class template. <TODO: further explanation here>

[File mt_range.h]
This gives you the simply way to get the first element of iterator from container/array as well as the end element of iterator from them.

begin() -- This will give the iteretor of the begin element taking the container/array in the argument.
cbegin() -- This will give the const iterator of the begin element taking the container/array in the argument.

end() -- This will give the iterator of the end element taking the container/array in the argument.
cend() -- This will give the const iterator of the end element taking the container/array in the argument.

[File mt_shim_clear_memory.h]
This gives you simply way to clear all the container/array. In case that some STL compliant container is put in this mt::clearMemory() shim function argument, clear() method will be invoked as a result of calling mt::clearMemory() function. In case that some arrayis put in this function argument, all the elements in the array are zero-ed as a result of calling mt::clearMemory() function.

[File mt_tuple.h]

=======================================================================================================
[cm] -> Common library

This is the software package that supports various 'aspects'. So in that sense, this should play
a role as core framework library under this software.

=======================================================================================================
cm_thread (libcm_thread.a)

Thread library which wraps several pthread APIs. Along with this
libary you will be able to also use 'inc/cm_thread_specific_data.h'
template library so that you can handle Thread-Specific Data storage per 'types'. See the unit
test code in 'cm/test/cm_thread_specific_data_test.cpp' for some hint.

This library also provides with 'mutex' which is useful to protect a certain 'resource' appropriately
under multi-thread environment. The way to use cm::Mutex is only allowed via nested 'Lock' class as
follows.

// Object instantiation
cm::Mutex mutex;

{
    cm::Mutex::Lock lock(mutex);
    // mutex is locked as long as this 'Lock' object is present.
}


It is recommended not to use this thread library directly. Instead it is recommended to use
cm::ThreadEventDriven class template so you don't need to take care much about thread management.
For more details, please take a look at cm/test/cm_thread_event_driven_test.cpp unit test code.
The only thing you are supposed to construct is to create some new class to declare/define some
action when some 'Event' happens as follows.

class SampleMessageHandler
{
public:
    SampleMessageHandler(cm::SocketIf* socket)
        : socket_if_(*socket)
    {
        cm::Event::tsdInstance().addHandlerRead(*this, &SampleMessageHandler::handleRead, socket_if_);
    }

    ~SampleMessageHandler()
    {
        cm::Event::tsdInstance().delHandlerRead(socket_if_);
    }

    static const char_t* getName() { return "sample_message_handler_thread"; }

    bool handleRead(cm::SocketIf& sock)
    {
        // implement operation here to read some data from socket etc..
    }

private:
    cm::SocketIf& socket_if_;
};

if you could prepare for the above handler class, then you can easily create the event-driven thread
as follows.

cm::ThreadEventDriven<SampleMessageHandler, cm::SocketIf> thread(&socket);
// The created thread above is present as long as the 'thread' class object is present...


=======================================================================================================
cm_event (libcm_event.a)

Event library which currently wraps epoll APIs (for Linux) and kqueue,kevent
APIs (for xxxBSD). This will be helpful to construct a event-driven basis programming styles. As
for Event types which can be used in conjunction with the Event class will be also provided in future.

=======================================================================================================
cm_socket (libcm_socket.a)

Socket library which wraps socket APIs. It supports Unix domain socket
(PF_LOCAL) and IPv4 socket (PF_INET). As for classes responsible for instantiation (factory),
cm::SocketServer and cm::SocketClient classes are introduced. These classes respectively have accept()
and connect() methods, which instantiate the cm::Socket class object whose lifetime is managed under
mt::AutoPtr<cm::SocketIf> RAII smart pointer.

-------------------------------------------------------------------------------------------------------
[cm::SocketIf class (Interface class)]

This is just an interface class which represents (network) socket. This interface class provides read
and write operation from/to the socket. It also provides 'clone' method, which may be helpful for unit
test purpose etc..

Although this interface class provides getFD() const method to get to know the exact socket descriptor
number, it is not recommend to use this public method in the client code directly. This getFD() member
method will be used by cm::Event class so that it can get the stimulus to realize event-driven callback
mechanism along with its getFD() free-function.

Basically the cm::SocketIf class family will hold RAII(RRID) idiom. Once this class object is
destructed, socket descriptor which is bound to this class object will be closed accordingly. This is
the way we realize the resource management of socket descriptors. If you need to give away its resource
control of the socket descriptor, release() public method will be used, which returns its socket
descriptor number and then notify its class object that it is no longer necessary to conduct the
resource desctruction.

<Public methods>
bool read(size_t& bytes_read, void* buf, size_t size_to_read)
    read() attempts 'size_to_read' bytes of data from the (network) socket referenced by the class
    object to the buffer pointed by buf. If successful, 'true' will be returned along with the number
    of succesfully read data in 'bytes_read' argument. If not successful, 'false' will be returned.

bool write(size_t& bytes_written, const void* buf, size_t size_to_write)
    write() attempts 'size_to_write' bytes of data to the (networ) socket referenced by the class
    object from the buffer pointed by buf. If successful, 'true' will be returned along with the number
    of successfully written data in 'bytes_written' argument. If not successful, 'false' will be
    returned.

int getFD() const
    getFD() simply gives the exact socket descriptor number. This function is not recommended to be
    used as this will impair object oriented design paradigm. The reason why this public method is
    prepared is that this is essential to make use of epoll-, kevent/kqueue- based callback mechanism
    as an entire framework. This public method will be used by cm::Event class for merely for this
    purpose.

int release()
    Similar to the above getFD() const method, this gives he exact socket descriptor number. However,
    the purpose of using this method is totally different than the above. 

    There is some case that you would need to enforce a cm::SocketIf class object to give away its
    resource management of socket descriptor. For example, this frame library also provies
    cm::VectorSocket class which enables gather-write (writev) operation towards the network
    socket. Although these two class objects don't have the same abstract class in common, these two
    object can be interchangeable i.e. when you firstly create some cm::SocketIf object and then pass
    this object refererence to instantiate the cm::VectorSocket class object by the following ctor
    statement.

    cm::SocketIf& socket_if = ...;  // Assume that this socket_if is bound to some concrete
                                    // cm::SocketIf class object.

    cm::VectorSocket vector_socket(socket_if);

    The above statement internally handles this release() method to transfer its resource control from
    cm::SocketIf to cm::VectorSocket so we don't need to be bothered by any double-free sort of issue.
    This is how this release() method will be used.

mt::AutoPtr<SocketIf> clone(int fd) const
    This clone() method will be used when you would like to realize some 'prototype pattern' style
    of programming. For the details of what is prototype pattern, please refer to authoritative book
    such as Design Pattern by GoF.

[cm::Socket class (Concrete class)]
    Basically this concreate class provides with the implementation of what the above interface class
    (cm::SocketIf) declare.