Home  /  RSS  /  RSS Comments  /  RSS for Framework  /  Project Site  /  Enter

Posts in category ‘Framework’.

CppCMS meets Comet

27/08/09, by artyom ; Posted in: Progress, Framework, Comet; 6 comments

One of the major requirements for framework refactoring was support of Comet. Now, with introduction of asynchronous request handling and persistent application servers it becomes reality.

Client Side

There is a HTML source of simple chat client, that uses Dojo toolkit. It does following:

  1. Submits new messages to the server application by posting form using XHR:

    function send_data() {
            var kw = {
                    url : "/chat/post",
                    form : "theform"
            };
            dojo.xhrPost(kw);
            dojo.byId("message").value="";
            return false;
    }
    
  2. Receives new messages from the server using long poll via XHR:

    var message_count = 0;
    function read_data() {
            dojo.xhrGet( {
                    url: "/chat/get/" + message_count,
                    timeout: 120000,
                    handleAs: "text",
                    load: function(response, ioArgs) {
                            dojo.byId("messages").innerHTML =
                                    response
                                    + '<br/>'
                                    + dojo.byId("messages").innerHTML;
                            message_count++;
                            read_data();
                            return response;
                    },
                    error: function(response,ioArgs) {
                            read_data();
                            return response;
                    }
    
            });
    }
    dojo.addOnLoad(read_data);
    

So, the client side is quite simple (however error handling should be quite better).

Server Side

First we create our long running asynchronous application, that receives two kinds for requests: "/post" – with new data, and "/get/NN" – receive message nuber NN, we assign these calls to two member functions post and get.

class chat : public cppcms::application {
public:
    chat(cppcms::service &srv) : cppcms::application(srv)
    {
        dispatcher().assign("^/post$",&chat::post,this);
        dispatcher().assign("^/get/(\\d+)$",&chat::get,this,1);
    }

Now, this class includes two data members:

private:
    std::vector<std::string> messages_;
    std::vector<cppcms::intrusive_ptr<cppcms::http::context> > waiters_;

The history of all chat messages – messages_ and all pending get requests that can’t be satisfied, because the message still not exists – waiters_

Each, "waiter" is actually pointer to request/response context that can be used for message transport.

Now, when new message arrives, post member function is called:

void post()
{
    if(request().request_method()=="POST") {
        if(request().post().find("message")!=request().post().end()) {
            messages_.push_back(request().post().find("message")->second);
            broadcast();
        }
    }
    release_context()->async_complete_response();
}

If the requested message was found, it is added to messages_ list and all waiters are notified using broadcast() member function.

At the end, the current request context is released and completed.

The broadcasting is done as following:

void broadcast()
{
    for(unsigned i=0;i<waiters_.size();i++) {
        waiters_[i]->response().set_plain_text_header();
        waiters_[i]->response().out() << messages_.back();
        waiters_[i]->async_complete_response();
        waiters_[i]=0;
    }
    waiters_.clear();
}

For each pending request the last message is written and the request closed. After that, all pending request are cleaned.

When get request arrives, it is handled by get(std::string no) member function, first of all we check if requested message exists, if so we just return it to user.

unsigned pos=atoi(no.c_str());
if(pos < messages_.size()) {
    response().set_plain_text_header();
    response().out()<<messages_[pos];
    release_context()->async_complete_response();
}

Otherwise, if the requested message is the last one, that does not exists, we add the request context to pending list waiters

else if(pos == messages_.size()) {
    waiters_.push_back(release_context());
}

If requested message it too late – probably client error, we just set status to "404 Not Found" and return the response.

else {
    response().status(404);
    release_context()->async_complete_response();
}

No, all we need to do is to add application to the main running loop under script name "/char" and start the service.

cppcms::service service(argc,argv);
cppcms::intrusive_ptr<chat> app=new chat(service);
service.applications_pool().mount(app,"/chat");
service.run();

Summary

So, the simple chat service was written with about 50 lines of C++ code and about same amount of JavaScript code.

I must admit, that it is too simplistic and not efficient, for example: if new client connects it receives all messages one by one and not as bulk (can be easily fixed), I do not handle timeouts and disconnects. But the general idea is quite clear:

This is actually a base for future development of tools like XML-RPC and JSON-RPC that allow client to call asynchronously server side objects, it can be used for implementation of any other Comet protocols.

Progress Report on CppCMS v1

17/08/09, by artyom ; Posted in: Progress, Framework; 3 comments

Its quite long time that most of the work is done in new refactoring branch… Meanwhile trunk stays silent. So, I decided to open a window and show some new changes:

There is still lot of work to make new version as useful as current CppCMS stable version:

But there are many good points that are already visible.

What's Next?

03/05/09, by artyom ; Posted in: Progress, FastCGI, Framework; 10 comments

The road map of the project includes two important milestones:

  1. CppCMS core components refactoring including following:
    • Removal of dependency on CgiCC – today there is about 5% of CgiCC library is used, many features are not supported by it or are not supported well. For example: file upload handling in CgiCC is very primitive, limited and error prone, support of cookies buggy and so on.
    • Using of Boost.Asio as internal event handler, because:
      1. It provides transparent synchronous and asynchronous event handling allowing future implementation of server push technologies.
      2. It provides efficient timer based event handling.
    • Removal dependency of libfcgi and writing Boost.Asio friendly implementation of FastCGI/SCGI connectors. Implementation of HTTP connectors as well.
    • Support of plug-in applications in CppCMS framework.
    • Improving compilation speed by representing more pimpl idioms and removal of unnecessary classes.
  2. Better support of i18n and and l10n:
    • Transparent support of std::wstring with forms including automatic encoding testing and conversion.
    • Support of std::locale for localization for outputs like numbers, dates, monetary, translation and so on.
    • Optional support of ICU and icu::UnicodeString and icu::Locale that would add unsupported features by std::locale and allow replacement std::locale features with more correct implementations provided by ICU.

These changes will significantly break API backward compatibility, but it would be possible to adopt the code almost "mechanically" to the new API.

Unicode in 2009? Why is it so hard?

15/04/09, by artyom ; Posted in: Framework, Unicode and Localization; 5 comments

From my point of view, one of the most missing features in C++ is the lack of good Unicode support. C++ provides some support via std::wstring and std::locale, but it is quite limited for real live purposes.

This definitely makes the life of C++ (Web) Developers harder.

However there are several tools and toolkits that provide such support. I had checked 6 of them: ICU library with bindings to C++, Java and Python, Qt3 and Qt4, glib/pango and native support of Java/JDK, C++ and Python.

I did little bit challenging test for correctness:

Basic features like encoding conversions and simple case conversion like "Артём" (my name in Russian) to "АРТЁМ" worked well in all tools. But more complicated test results were quite bad:

Results

TookitTo Upper CaseTo Lower CaseWord Boundaries
C++FailFailNo Support
C++/ICU‎OkOkOk
C++/Qt4‎OkFailOk
C++/Qt3‎FailFailNo Support
C/glib+pangoOkOkFail
Java/JDKOkOkFail
Java/ICU4jOkOkOk
PythonFailFailNo Support
Python/PyICU‎OkOkOk

Description

ICU: Provides great support but… it has very unfriendly and old API in terms of C++ development. The documentation is really bad.

Qt4: Gives good results and friendly API, has great documentation, but as we can see, some tests are failed. Generally, useful in web projects.

Qt3: Provides very basic Unicode support, no reason to use any more, especially when Qt4.5 is released under LGPL.

C++/STL: Even basic support exists, the API is not too friendly to STL containers and requires explicit usage of char * or wchar_t * and manual buffers allocation.

Glib: Gives quite good basic functionality. But finding word boundaries with Pango is really painful and does not work with Chinese. It has very nice C API and quite well documented. It uses internally utf-8 which makes the life easier when working with C strings. It still requires wrapping its functionality with C++ classes or grabbing huge GtkMM.

Python: has very basic native Unicode support. PyICU has terrible documentation.

Java: JDK provides quite good Unicode support, it can be quite easily replaced by ICU4J (actually most of JDK is based on ICU).

Summary

It is a shame that in 2009 there is no high quality, well documented, C++ friendly toolkit to work with Unicode.

When there will be Boost.ICU or Boost.Unicode just like there is Boost.Math or Boost.Asio?

CppCMS 0.0.4 Released

21/02/09, by artyom ; Posted in: Progress, Framework, Cache; 0 comments

Version 0.0.4 of CppCMS had released.

It includes optimizations required for using it in embedded systems.

Normal Embedded Build:

Embedded CGI Mode:

Downloads are avialable from Sf Project Page.

Pages

Categories

Development

Powered By

3rd Party