
Hello fellow boosters, after months of lurking on this list and seeing how everybody seems to have its own network library, i've finally decided to put online mine. I will upload it under the vault as nanostream.tar.gz, it is unix/linux only currently. You may want to skip the library code and read the pdf under the doc directory where the library is shortly presented and some examples are given. These are the main features/peculiarities of my library: - There is no socket concept because i don't really think it is natural, at least not for a C++ programmer. I use the acceptor, connector and stream concepts. - User is not required to reference streams by pointer, streams are stack allocated or are simply members of another object. Internally they have a smart pointer to an implementaion handle. Consider them stack-based proxies. The acceptor and the connector return the handle that is asigned to the stream. - The preferred way to do input output is to use standard-like algorithms (i.e. copy) with buffered stream adaptors and specialized input/output iterators. I believe that an efficient library can be written this way and be very C++-user-friendly. Classic read/write are still available, but their semantics might be surprising. - All classes are concrete, no polymorphism is used (i.e. no virtuals). Polimorphic behaviour must currently be achieved with some external mean (i.e using the external polymorphism pattern. I think that the boost::IDL library would be great). - Errors can be reported both with exceptions and with error codes. Exceptions are used by default unless error callbacks are passed. This seems to work quite well. Internally only error codes are used and exceptions are thrown only at the most external abstracion layer. Note that the library does not actually use error codes, but error types using a specialized variant object. This is just an experiment and i might remove it. I will probably add status bits a-la iostreams. - File streams. The library actually try to be a generalized i/o framework, and file streams are provided for completeness. - The library can be extended simply by creating new handles. In addition to TCP streams there are Unix streams (come almost for free :-) and file streams. SSL/TLS was present but did get broken some time ago and didn't have the time to fix it. - Input/Output buffer. This is very similar to a std::deque<char>. It has segmented iterators support (the same interface presented in the Austern paper), and it is the preferred input/output buffer, it can be easilly grown on both directions (usefull if you need to add an header) and can be efficiently read/written with scatter-gather operations. While i have yet to implement it, i think that moving data from a buffer to another can be done extremely efficently by splicing the internal pages. The buffer is also used to implement the buffered adapter. boost::arrays, vectors and plain arrays also work fine, while other containers require a bounce buffer and thus slower operations. - Addresses are logically defined by a triplet <domain, host, service>, where the domain is implicit in the acceptor, address, or connector type, host and service are two strings. This is inspired by the getnameinfo(3) interface. - A multithreaded stream adaptor and an http module are also included. These are just proof of concept and not really part of the library (yet). Missing (definitelly not complete list): The library is fully sinchronous for now. I'm still considering how to add asynch support. I think i will implement it in the buffered adaptor I/O is done asynchronously to the internal buffers that can grow as much as it is necessary. Timeouts are definitelly a must-have. Final notes: I've have seen that the current consens is to encode the the stream type in the address, so to allow a dynamic behaviour: the actual transport is selected only at runtime, based on the address string. I think this is a bad decision (i considered doing it while implementing my library) and this is why: - C++ is a static language, let's leave these niceties to more dynamic languages. I have found myself weeks hunting a bug in the http code because i thought that it would be cool if i could access http properties using a map instead of proper accessor functions. I spent weeks hunting persistent connection bug. It was a simple typo inside a http property string that would have been caught immediately by the compiler if i were using functions or costants [1]. - It mimics standard library usage. You cannot open the input stream instead of a file by using the "input:" file name. (well under Unix you might actually do it, but i don't think this was the intention of the standard library authors and it is not portable any way). - It is extremely insecure. In a network library security must be paramount. If the transport type were encoded in the address, it would be much harder to validate externally received addresses. A similar argument can be made for the port numbers. It is better to keep these things separated. The library user can create its own indexed factory collection if it really needs to. Sorry for the long post, just tryin' to be usefull :-). -- Giovanni P. Deretta 1 - I did write "Content-Length" instead of "Content-Lenght".