* basic HTTP parsing
authorMichal Voců <michal@ruk.cuni.cz>
Wed, 7 Mar 2007 20:16:50 +0000 (20:16 +0000)
committerMichal Voců <michal@ruk.cuni.cz>
Wed, 7 Mar 2007 20:16:50 +0000 (20:16 +0000)
org.glite.lb.logger/src-nt/HTTPTransport.H
org.glite.lb.logger/src-nt/HTTPTransport.cpp
org.glite.lb.logger/src-nt/ThreadPool.H

index d5bf700..417deea 100644 (file)
@@ -25,26 +25,32 @@ public:
        HTTPTransport(Connection *conn) 
                : Transport(conn),
                  state(NONE),
-                 request(), headers(), body(NULL), pos(NULL)
+                 request(), headers(), body(NULL), pos(NULL),
+                 content_length(0)
                {}
 
        virtual ~HTTPTransport();
 
+
+protected:
        // from ThreadPool::WorkDescription
        virtual void onReady();
        virtual void onTimeout();
        virtual void onError();
 
-protected:
+private:
        enum { NONE, 
               IN_REQUEST,
               IN_HEADERS,
               IN_BODY } state;
-       string request;
-       string headers;
+       std::string request;
+       std::string headers;
        char *body;
        char buffer[256];
        char *pos;
+       unsigned int content_length;
+
+       int parseHeader(const char *s, unsigned int len);
 };
 
 
index 61d67f2..9847beb 100644 (file)
@@ -16,6 +16,8 @@ HTTPTransport::~HTTPTransport()
 void
 HTTPTransport::onReady()
 {
+       int len;
+
        switch(state) {
        case NONE:
                state = IN_REQUEST;
@@ -23,30 +25,98 @@ HTTPTransport::onReady()
 
        case IN_REQUEST:
        case IN_HEADERS:
-               len = conn->read(buffer, sizeof(buffer));
+               len = conn->read(pos, sizeof(buffer) - (pos - buffer));
                if(len < 0) {
                        // error during request
                } else if(len == 0) {
                        // other side closed connection
                } else {
-                       char *cr;
-
-                       // parse buffer, look for CRLF
-                       cr = memchr(buffer, '\r', len);
-                       if(cr) {
-                               if((cr < buffer + len - 1) &&
+                       char *cr = NULL, *p = buffer, *s = buffer;
+                       bool crlf_seen = false;
+
+                       // parse buffer, look for CRLFs
+                       //   s - start scan position
+                       //   p - start of current token
+                       //   cr - current CRLF position
+                       //   crlf_seen <=> previous block ends with CRLF
+                       while((state != IN_BODY) &&
+                             (s < buffer + len) && 
+                             (cr = (char*)memchr(s, '\r', len - (s - buffer)))) {
+                               if((cr < buffer + len - 1) && 
                                   (cr[1] == '\n')) {
                                        // found CRLF
-                                       
-                               } else 
-                                       cr = buffer + len;
+                                       if(state == IN_REQUEST) {
+                                               // found end of request
+                                               request.append(p, cr - p);
+                                               // change state
+                                               state = IN_HEADERS;
+                                               // start new tokens
+                                               p = cr + 2;
+                                       } else {
+                                               // headers continue. parse the current one
+                                               parseHeader(s, cr - s);
+                                       }
+                                       if(crlf_seen && (s == cr)) {
+                                               // found CRLFCRLF
+                                               state = IN_BODY;
+                                       } 
+                                       // next scan starts after CRLF
+                                       s = cr + 2; 
+                                       // we have seen CRLF
+                                       crlf_seen = true;
+                               } else {
+                                       if(crlf_seen && (s == cr)) {
+                                               if(cr < buffer + len - 1) {
+                                                       // found CRLFCRx
+                                                       // continue scan behind this
+                                                       s = cr + 2;
+                                               } else {
+                                                       // found CRLFCR at the end of buffer
+                                                       // s points behind buffer => scan ends
+                                                       s = cr + 1;
+                                                       // cr points at the CRLFCR => it will be left for next pass
+                                                       cr = cr - 2;
+                                               }
+                                       } else {
+                                               // single '\r'  - skip it, 
+                                               // or '\r' at the end of buffer - skip it, that ends scanning
+                                               s = cr + 1;
+                                       }       
+                                       crlf_seen = false;
+                               }
                        }
-                       // append everything up to the cr into appropriate variable
+                       // copy the current token into appropriate variable,
+                       // but leave the trailing \r[\n] in buffer
+                       if(!cr) cr = buffer + len;
                        if(state == IN_REQUEST) 
-                               request.append(buffer, cr - buffer);
-                       else
-                               headers.append(buffer, cr - buffer);
+                               request.append(p, cr - p);
+                       else 
+                               headers.append(p, cr - p);
+                       if(state == IN_BODY) {
+                               // we found body
+                               // content-length should be set at the moment
+                               if(content_length > 0) {
+                                       body = (char*)malloc(content_length);
+                                       if(body == NULL) {
+                                               // chyba alokace
+                                       }
+                                       // move rest of buffer to body
+                                       if(s < buffer + len) {
+                                               memmove(body, s, buffer + len - s);
+                                               pos = body + (buffer + len - s);
+                                       }
+                               } else {
+                                       // report error
+                               }
+                       } else {
+                               // move the trailing characters to the front
+                               if(cr < buffer + len) 
+                                       memmove(buffer, cr, buffer + len - cr);
+                               // and set pos to point at the first free place
+                               pos = buffer + (buffer + len - cr);
+                       }
                }
+               break;
 
        case IN_BODY:
                break;
@@ -67,3 +137,9 @@ HTTPTransport::onError()
 }
 
 
+int
+HTTPTransport::parseHeader(const char *s, unsigned int len)
+{
+       std::cout.write(s, len);
+       return(0);
+}
index 602b86b..9c17de9 100644 (file)
@@ -19,6 +19,11 @@ public:
                WorkDescription(int afd) 
                        : fd(afd), event(NONE) {}
 
+
+       protected:
+               enum Event { NONE, READY, TIMEOUT, ERROR } event;
+               void doWork();
+
                virtual void onReady() 
                        {}
 
@@ -27,10 +32,6 @@ public:
 
                virtual void onError() 
                        {}
-
-       protected:
-               enum Event { NONE, READY, TIMEOUT, ERROR } event;
-               void doWork();
        };
 
 public: