io_http.c

Go to the documentation of this file.
00001 /***************************************************************************
00002  $RCSfile$
00003                              -------------------
00004     cvs         : $Id: crypttoken.h 1113 2007-01-10 09:14:16Z martin $
00005     begin       : Wed Mar 16 2005
00006     copyright   : (C) 2005 by Martin Preuss
00007     email       : martin@libchipcard.de
00008 
00009  ***************************************************************************
00010  *          Please see toplevel file COPYING for license details           *
00011  ***************************************************************************/
00012 
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 #endif
00016 
00017 
00018 #include "io_http_p.h"
00019 #include <gwenhywfar/iolayer_be.h>
00020 #include <gwenhywfar/iorequest_be.h>
00021 #include <gwenhywfar/iomanager.h>
00022 #include <gwenhywfar/io_buffered.h>
00023 
00024 #include "i18n_l.h"
00025 #include <gwenhywfar/misc.h>
00026 #include <gwenhywfar/debug.h>
00027 #include <gwenhywfar/gui.h>
00028 #include <gwenhywfar/text.h>
00029 
00030 #include <assert.h>
00031 #include <ctype.h>
00032 
00033 
00034 
00035 
00036 GWEN_INHERIT(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP)
00037 
00038 
00039 
00040 
00041 
00042 GWEN_IO_LAYER *GWEN_Io_LayerHttp_new(GWEN_IO_LAYER *baseLayer) {
00043   GWEN_IO_LAYER *io;
00044   GWEN_IO_LAYER_HTTP *xio;
00045 
00046   io=GWEN_Io_Layer_new(GWEN_IO_LAYER_HTTP_TYPE, baseLayer);
00047   assert(io);
00048   GWEN_NEW_OBJECT(GWEN_IO_LAYER_HTTP, xio);
00049   assert(xio);
00050   GWEN_INHERIT_SETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io, xio, GWEN_Io_LayerHttp_freeData);
00051 
00052   xio->dbCommandIn=GWEN_DB_Group_new("command");
00053   xio->dbStatusIn=GWEN_DB_Group_new("status");
00054   xio->dbHeaderIn=GWEN_DB_Group_new("header");
00055   xio->readBuffer=GWEN_Buffer_new(0, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE, 0, 1);
00056 
00057   xio->dbCommandOut=GWEN_DB_Group_new("command");
00058   xio->dbStatusOut=GWEN_DB_Group_new("status");
00059   xio->dbHeaderOut=GWEN_DB_Group_new("header");
00060   xio->writeBuffer=GWEN_Buffer_new(0, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE, 0, 1);
00061 
00062   GWEN_Io_Layer_SetWorkOnRequestsFn(io, GWEN_Io_LayerHttp_WorkOnRequests);
00063   GWEN_Io_Layer_SetAddRequestFn(io, GWEN_Io_LayerHttp_AddRequest);
00064   GWEN_Io_Layer_SetDelRequestFn(io, GWEN_Io_LayerHttp_DelRequest);
00065   GWEN_Io_Layer_SetHasWaitingRequestsFn(io, GWEN_Io_LayerHttp_HasWaitingRequests);
00066 
00067   return io;
00068 }
00069 
00070 
00071 
00072 GWENHYWFAR_CB
00073 void GWEN_Io_LayerHttp_freeData(GWEN_UNUSED void *bp, void *p) {
00074   GWEN_IO_LAYER_HTTP *xio;
00075 
00076   xio=(GWEN_IO_LAYER_HTTP*) p;
00077   GWEN_DB_Group_free(xio->dbCommandIn);
00078   GWEN_DB_Group_free(xio->dbStatusIn);
00079   GWEN_DB_Group_free(xio->dbHeaderIn);
00080   GWEN_Buffer_free(xio->readBuffer);
00081 
00082   GWEN_DB_Group_free(xio->dbCommandOut);
00083   GWEN_DB_Group_free(xio->dbStatusOut);
00084   GWEN_DB_Group_free(xio->dbHeaderOut);
00085   GWEN_Buffer_free(xio->writeBuffer);
00086 
00087   GWEN_FREE_OBJECT(xio);
00088 }
00089 
00090 
00091 
00092 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbCommandIn(const GWEN_IO_LAYER *io) {
00093   GWEN_IO_LAYER_HTTP *xio;
00094 
00095   assert(io);
00096   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00097   assert(xio);
00098 
00099   return xio->dbCommandIn;
00100 }
00101 
00102 
00103 
00104 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbStatusIn(const GWEN_IO_LAYER *io) {
00105   GWEN_IO_LAYER_HTTP *xio;
00106 
00107   assert(io);
00108   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00109   assert(xio);
00110 
00111   return xio->dbStatusIn;
00112 }
00113 
00114 
00115 
00116 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbHeaderIn(const GWEN_IO_LAYER *io) {
00117   GWEN_IO_LAYER_HTTP *xio;
00118 
00119   assert(io);
00120   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00121   assert(xio);
00122 
00123   return xio->dbHeaderIn;
00124 }
00125 
00126 
00127 
00128 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbCommandOut(const GWEN_IO_LAYER *io) {
00129   GWEN_IO_LAYER_HTTP *xio;
00130 
00131   assert(io);
00132   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00133   assert(xio);
00134 
00135   return xio->dbCommandOut;
00136 }
00137 
00138 
00139 
00140 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbStatusOut(const GWEN_IO_LAYER *io) {
00141   GWEN_IO_LAYER_HTTP *xio;
00142 
00143   assert(io);
00144   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00145   assert(xio);
00146 
00147   return xio->dbStatusOut;
00148 }
00149 
00150 
00151 
00152 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbHeaderOut(const GWEN_IO_LAYER *io) {
00153   GWEN_IO_LAYER_HTTP *xio;
00154 
00155   assert(io);
00156   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00157   assert(xio);
00158 
00159   return xio->dbHeaderOut;
00160 }
00161 
00162 
00163 
00164 void GWEN_Io_LayerHttp_AbortInRequests(GWEN_IO_LAYER *io, int errorCode) {
00165   GWEN_IO_LAYER_HTTP *xio;
00166 
00167   assert(io);
00168   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00169   assert(xio);
00170 
00171   if (xio->readRequestIn) {
00172     GWEN_IO_REQUEST *r;
00173 
00174     r=xio->readRequestIn;
00175     xio->readRequestIn=NULL;
00176     DBG_INFO(GWEN_LOGDOMAIN, "Aborting in read request");
00177     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00178     GWEN_Io_Request_free(r);
00179   }
00180   if (xio->writeRequestIn) {
00181     GWEN_IO_REQUEST *r;
00182 
00183     r=xio->writeRequestIn;
00184     xio->writeRequestIn=NULL;
00185     DBG_INFO(GWEN_LOGDOMAIN, "Aborting in write request");
00186     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00187     GWEN_Io_Request_free(r);
00188   }
00189 }
00190 
00191 
00192 
00193 void GWEN_Io_LayerHttp_AbortOutRequests(GWEN_IO_LAYER *io) {
00194   GWEN_IO_LAYER_HTTP *xio;
00195 
00196   assert(io);
00197   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00198   assert(xio);
00199 
00200   if (xio->readRequestOut) {
00201     GWEN_IO_REQUEST *r;
00202 
00203     r=xio->readRequestOut;
00204     GWEN_Io_Layer_DelRequest(GWEN_Io_Layer_GetBaseLayer(io), r);
00205     xio->readRequestOut=NULL;
00206     GWEN_Io_Request_free(r);
00207   }
00208   if (xio->writeRequestIn) {
00209     GWEN_IO_REQUEST *r;
00210 
00211     r=xio->writeRequestIn;
00212     GWEN_Io_Layer_DelRequest(GWEN_Io_Layer_GetBaseLayer(io), r);
00213     xio->writeRequestIn=NULL;
00214     GWEN_Io_Request_free(r);
00215   }
00216 }
00217 
00218 
00219 
00220 
00221 
00222 int GWEN_Io_LayerHttp_ParseCommand(GWEN_IO_LAYER *io, const char *buffer) {
00223   GWEN_IO_LAYER_HTTP *xio;
00224   char *tmp;
00225   char *p;
00226   char *s;
00227 
00228   assert(io);
00229   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00230   assert(xio);
00231 
00232   tmp=strdup(buffer);
00233   s=tmp;
00234 
00235   /* read command */
00236   p=strchr(s, ' ');
00237   if (!p) {
00238     DBG_ERROR(GWEN_LOGDOMAIN,
00239               "Bad format of HTTP request (%s)", buffer);
00240     free(tmp);
00241     return GWEN_ERROR_INVALID;
00242   }
00243   *p=0;
00244   p++;
00245 
00246   GWEN_DB_SetCharValue(xio->dbCommandIn, GWEN_DB_FLAGS_OVERWRITE_VARS, "command", s);
00247   s=p;
00248 
00249   /* read URL */
00250   p=strchr(s, ' ');
00251   if (!p) {
00252     /* be less strict n IPC mode */
00253     if (GWEN_Io_Layer_GetFlags(io) & GWEN_IO_LAYER_HTTP_FLAGS_IPC) {
00254       DBG_INFO(GWEN_LOGDOMAIN, "Ignoring missing url");
00255       free(tmp);
00256       return 0;
00257     }
00258     else {
00259       DBG_ERROR(GWEN_LOGDOMAIN,
00260                 "Bad format of HTTP request (%s)", buffer);
00261       free(tmp);
00262       return GWEN_ERROR_INVALID;
00263     }
00264   }
00265   *p=0;
00266   p++;
00267 
00268   GWEN_DB_SetCharValue(xio->dbCommandIn, GWEN_DB_FLAGS_OVERWRITE_VARS, "url", s);
00269   s=p;
00270 
00271   if (*s==0) {
00272     /* no protocol information follows, so we assume HTTP/0.9 */
00273     DBG_ERROR(GWEN_LOGDOMAIN, "Bad request (not in HTTP>=1.0)");
00274     free(tmp);
00275     return GWEN_ERROR_INVALID;
00276   }
00277   else {
00278     GWEN_DB_SetCharValue(xio->dbCommandIn, GWEN_DB_FLAGS_OVERWRITE_VARS, "protocol", s);
00279   }
00280 
00281   free(tmp);
00282   return 0;
00283 }
00284 
00285 
00286 
00287 int GWEN_Io_LayerHttp_ParseStatus(GWEN_IO_LAYER *io, const char *buffer) {
00288   GWEN_IO_LAYER_HTTP *xio;
00289   char *tmp;
00290   char *p;
00291   char *s;
00292   int code;
00293 
00294   assert(io);
00295   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00296   assert(xio);
00297 
00298   tmp=strdup(buffer);
00299   s=tmp;
00300 
00301   /* read protocol */
00302   p=strchr(s, ' ');
00303   if (!p) {
00304     DBG_ERROR(GWEN_LOGDOMAIN,
00305               "Bad format of HTTP status (%s)", buffer);
00306     free(tmp);
00307     return GWEN_ERROR_INVALID;
00308   }
00309   *p=0;
00310   p++;
00311 
00312   GWEN_DB_SetCharValue(xio->dbStatusIn, GWEN_DB_FLAGS_OVERWRITE_VARS, "protocol", s);
00313   s=p;
00314 
00315   /* read status code */
00316   while(*p && isdigit((int)*p))
00317     p++;
00318   if (*p) {
00319     *p=0;
00320     p++;
00321   }
00322   if (1!=sscanf(s, "%d", &code)) {
00323     DBG_ERROR(GWEN_LOGDOMAIN, "Bad request (status code \"%s\")", s);
00324     free(tmp);
00325     return GWEN_ERROR_INVALID;
00326   }
00327   GWEN_DB_SetIntValue(xio->dbStatusIn, GWEN_DB_FLAGS_OVERWRITE_VARS, "code", code);
00328   s=p;
00329 
00330   /* read text */
00331   GWEN_DB_SetCharValue(xio->dbStatusIn, GWEN_DB_FLAGS_OVERWRITE_VARS, "text", s);
00332 
00333   free(tmp);
00334   return 0;
00335 }
00336 
00337 
00338 
00339 int GWEN_Io_LayerHttp_ParseHeader(GWEN_IO_LAYER *io, char *buf) {
00340   GWEN_IO_LAYER_HTTP *xio;
00341   char *p;
00342   const char *s;
00343 
00344   assert(io);
00345   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00346   assert(xio);
00347 
00348   /* resolve line continuations */
00349   p=buf;
00350   while(*p) {
00351     p=strchr(p, 10);
00352     if (p) {
00353       if (p[1]==32 || p[1]==9)
00354         /* found a continuation */
00355         *p=32;
00356       p++;
00357     }
00358   }
00359 
00360   /* parse every line */
00361   p=buf;
00362   while(p && *p) {
00363     char *pNext;
00364     char *pVarBegin;
00365     char *pVarEnd;
00366 
00367     /* skip blanks */
00368     pNext=strchr(p, 10);
00369     if (pNext) {
00370       *pNext=0;
00371       pNext++;
00372     }
00373     while(*p && (*p==32 || *p==9))
00374       p++;
00375     if (*p) {
00376       pVarBegin=p;
00377       while(*p && *p!=':' && *p>32 && *p<127)
00378         p++;
00379       pVarEnd=p;
00380       if (*p!=':') {
00381         DBG_INFO(GWEN_LOGDOMAIN, "No separator after variable name in received header");
00382         return GWEN_ERROR_BAD_DATA;
00383       }
00384       *pVarEnd=0;
00385       p++;
00386 
00387       while(*p && (*p==32 || *p==9))
00388         p++;
00389       if (*p)
00390         GWEN_DB_SetCharValue(xio->dbHeaderIn, GWEN_PATH_FLAGS_CREATE_VAR, pVarBegin, p);
00391     }
00392     p=pNext;
00393   }
00394 
00395   /* default next mode after reading the header is reading the body
00396    * (if any, but that will be checked later) */
00397   xio->readMode=GWEN_Io_LayerHttp_Mode_Body;
00398 
00399   /* header received, now read some settings from it */
00400   s=GWEN_DB_GetCharValue(xio->dbHeaderIn, "Transfer-Encoding", 0, 0);
00401   if (s && (-1!=GWEN_Text_ComparePattern(s, "*chunked*", 0))) {
00402     /* chunked encoding, this means next we have to read the chunksize */
00403     xio->currentReadChunkSize=-1;
00404     xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
00405   }
00406 
00407   /* get size of body */
00408   xio->currentReadBodySize=GWEN_DB_GetIntValue(xio->dbHeaderIn, "Content-Length", 0, -1);
00409   if (xio->currentReadBodySize==0) {
00410     /* no body */
00411     xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00412   }
00413   if (xio->currentReadBodySize==-1) {
00414     int rcode;
00415 
00416     /* no length of body received, assume 0 in case of an error
00417      * This eliminates the bug where this module waits for
00418      * a timeout when receiving an error from a special server
00419      */
00420     rcode=GWEN_DB_GetIntValue(xio->dbStatusIn, "code", 0, -1);
00421     if (rcode<0 || rcode>=300) {
00422       /* no body */
00423       xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00424     }
00425   }
00426 
00427   return 0;
00428 }
00429 
00430 
00431 
00432 int GWEN_Io_LayerHttp_WriteCommand(GWEN_IO_LAYER *io, GWEN_BUFFER *buf) {
00433   GWEN_IO_LAYER_HTTP *xio;
00434   const char *s;
00435 
00436   assert(io);
00437   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00438   assert(xio);
00439 
00440   s=GWEN_DB_GetCharValue(xio->dbCommandOut, "command", 0, "GET");
00441   GWEN_Buffer_AppendString(buf, s);
00442   GWEN_Buffer_AppendString(buf, " ");
00443 
00444   s=GWEN_DB_GetCharValue(xio->dbCommandOut, "url", 0, "/");
00445   GWEN_Buffer_AppendString(buf, s);
00446   GWEN_Buffer_AppendString(buf, " ");
00447 
00448   s=GWEN_DB_GetCharValue(xio->dbCommandOut, "protocol", 0, "HTTP/1.0");
00449   GWEN_Buffer_AppendString(buf, s);
00450   GWEN_Buffer_AppendString(buf, "\r\n");
00451 
00452   return 0;
00453 }
00454 
00455 
00456 
00457 int GWEN_Io_LayerHttp_WriteStatus(GWEN_IO_LAYER *io, GWEN_BUFFER *buf) {
00458   GWEN_IO_LAYER_HTTP *xio;
00459   const char *s;
00460   int i;
00461   char numbuf[32];
00462 
00463   assert(io);
00464   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00465   assert(xio);
00466 
00467   s=GWEN_DB_GetCharValue(xio->dbStatusOut, "protocol", 0, "HTTP/1.0");
00468   GWEN_Buffer_AppendString(buf, s);
00469   GWEN_Buffer_AppendString(buf, " ");
00470 
00471   i=GWEN_DB_GetIntValue(xio->dbStatusOut, "code", 0, -1);
00472   if (i==-1) {
00473     DBG_INFO(GWEN_LOGDOMAIN, "Missing status code");
00474     return GWEN_ERROR_NO_DATA;
00475   }
00476   snprintf(numbuf, sizeof(numbuf), "%d ", i);
00477   GWEN_Buffer_AppendString(buf, numbuf);
00478 
00479   s=GWEN_DB_GetCharValue(xio->dbStatusOut, "text", 0, "No text.");
00480   GWEN_Buffer_AppendString(buf, s);
00481   GWEN_Buffer_AppendString(buf, "\r\n");
00482 
00483   return 0;
00484 }
00485 
00486 
00487 
00488 int GWEN_Io_LayerHttp_WriteHeader(GWEN_IO_LAYER *io, GWEN_BUFFER *buf) {
00489   GWEN_IO_LAYER_HTTP *xio;
00490   int i;
00491   GWEN_DB_NODE *dbVar;
00492 
00493   assert(io);
00494   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00495   assert(xio);
00496 
00497   i=GWEN_DB_GetIntValue(xio->dbHeaderOut, "Content-Length", 0, -1);
00498   if (i!=-1)
00499     xio->currentWriteBodySize=i;
00500 
00501   dbVar=GWEN_DB_GetFirstVar(xio->dbHeaderOut);
00502   while (dbVar) {
00503     GWEN_DB_NODE *dbVal;
00504 
00505     /* only handle first value */
00506     dbVal=GWEN_DB_GetFirstValue(dbVar);
00507     if (dbVal) {
00508       GWEN_DB_NODE_TYPE vtype;
00509 
00510       vtype=GWEN_DB_GetValueType(dbVal);
00511       if (vtype==GWEN_DB_NodeType_ValueChar) {
00512         const char *s;
00513 
00514         GWEN_Buffer_AppendString(buf, GWEN_DB_VariableName(dbVar));
00515         GWEN_Buffer_AppendString(buf, ":");
00516         s=GWEN_DB_GetCharValueFromNode(dbVal);
00517         if (s)
00518           GWEN_Buffer_AppendString(buf, s);
00519         GWEN_Buffer_AppendString(buf, "\r\n");
00520       }
00521       else if (vtype==GWEN_DB_NodeType_ValueInt) {
00522         i=GWEN_DB_GetIntValueFromNode(dbVal);
00523         if (i!=-1 || strcasecmp(GWEN_DB_VariableName(dbVar), "Content-Length")==0) {
00524           char numbuf[32];
00525 
00526           /* dont write body size of -1 */
00527           GWEN_Buffer_AppendString(buf, GWEN_DB_VariableName(dbVar));
00528           GWEN_Buffer_AppendString(buf, ":");
00529           snprintf(numbuf, sizeof(numbuf), "%d", i);
00530           GWEN_Buffer_AppendString(buf, numbuf);
00531           GWEN_Buffer_AppendString(buf, "\r\n");
00532         }
00533       }
00534       else {
00535         DBG_INFO(GWEN_LOGDOMAIN, "Variable type %d of var [%s] not supported",
00536                  vtype, GWEN_DB_VariableName(dbVar));
00537         return GWEN_ERROR_BAD_DATA;
00538       }
00539     }
00540     dbVar=GWEN_DB_GetNextVar(dbVar);
00541   }
00542 
00543   /* finalize header */
00544   GWEN_Buffer_AppendString(buf, "\r\n");
00545 
00546   return 0;
00547 }
00548 
00549 
00550 
00551 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest1(GWEN_IO_LAYER *io) {
00552   GWEN_IO_LAYER_HTTP *xio;
00553   int doneSomething=0;
00554 
00555   assert(io);
00556   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00557   assert(xio);
00558 
00559   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest1 (%d)", xio->readMode);
00560 
00561   if (xio->readRequestOut) {
00562     /* check for finished outbound read request */
00563     if (GWEN_Io_Request_GetStatus(xio->readRequestOut)==GWEN_Io_Request_StatusFinished) {
00564       uint32_t bpos;
00565       uint32_t flags;
00566 
00567       doneSomething=1;
00568 
00569       /* get all available data */
00570       xio->lastReadOutResult=GWEN_Io_Request_GetResultCode(xio->readRequestOut);
00571       flags=GWEN_Io_Request_GetFlags(xio->readRequestOut);
00572       bpos=GWEN_Io_Request_GetBufferPos(xio->readRequestOut);
00573 
00574       /* adjusting buffer pointers */
00575       GWEN_Buffer_IncrementPos(xio->readBuffer, bpos);
00576       GWEN_Buffer_AdjustUsedBytes(xio->readBuffer);
00577 
00578       if (flags & GWEN_IO_REQUEST_FLAGS_PACKETEND) {
00579         xio->readLineFinished=1;
00580       }
00581 
00582       DBG_VERBOUS(GWEN_LOGDOMAIN, "Received %d bytes (%s)",
00583                   bpos, (xio->readLineFinished)?"line finished":"line open");
00584 
00585       /* request handled */
00586       GWEN_Io_Request_free(xio->readRequestOut);
00587       xio->readRequestOut=NULL;
00588     }
00589   } /* if readRequestOut */
00590 
00591   if (xio->readRequestIn) {
00592     GWEN_IO_REQUEST *rIn;
00593 
00594     rIn=xio->readRequestIn;
00595     if (xio->readLineFinished==0) {
00596       if (xio->readRequestOut==NULL) {
00597         int rv;
00598 
00599         if (xio->lastReadOutResult) {
00600           xio->readRequestIn=NULL;
00601           DBG_INFO(GWEN_LOGDOMAIN, "Aborting out read request (reason: %d)",
00602                    xio->lastReadOutResult);
00603           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00604           GWEN_Io_Request_free(rIn);
00605           rIn=NULL;
00606           doneSomething=1;
00607         }
00608         else {
00609           rv=GWEN_Buffer_AllocRoom(xio->readBuffer, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00610           if (rv<0) {
00611             xio->readRequestIn=NULL;
00612             xio->lastReadOutResult=GWEN_ERROR_MEMORY_FULL;
00613             DBG_INFO(GWEN_LOGDOMAIN, "Aborting out read request (reason: %d)",
00614                      xio->lastReadOutResult);
00615             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_MEMORY_FULL);
00616             GWEN_Io_Request_free(rIn);
00617             rIn=NULL;
00618             doneSomething=1;
00619           }
00620           else {
00621             GWEN_IO_REQUEST *rOut;
00622 
00623             DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d header bytes", GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00624             rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00625                                      (uint8_t*)GWEN_Buffer_GetPosPointer(xio->readBuffer),
00626                                      GWEN_IO_LAYER_HTTP_LINE_STEPSIZE,
00627                                      NULL, NULL,
00628                                      GWEN_Io_Request_GetGuiId(rIn));
00629             rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00630             if (rv) {
00631               if (rv!=GWEN_ERROR_TRY_AGAIN) {
00632                 GWEN_Io_Request_free(rOut);
00633                 xio->readRequestIn=NULL;
00634                 xio->lastReadOutResult=rv;
00635                 DBG_INFO(GWEN_LOGDOMAIN,
00636                          "Aborting out read request (reason: %d)",
00637                          xio->lastReadOutResult);
00638                 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00639                 GWEN_Io_Request_free(rIn);
00640                 rIn=NULL;
00641                 doneSomething=1;
00642               }
00643             }
00644             else {
00645               DBG_DEBUG(GWEN_LOGDOMAIN, "Added header read request");
00646               xio->readRequestOut=rOut;
00647               doneSomething=1;
00648             }
00649           } /* if allocRoom succeeded */
00650         } /* if last result was ok */
00651       } /* if no readRequestOut */
00652     } /* if line not finished */
00653     else {
00654       int rv;
00655 
00656       /* line finished */
00657       doneSomething=1;
00658       xio->readLineFinished=0; /* reset for next line */
00659       switch(xio->readMode) {
00660       case GWEN_Io_LayerHttp_Mode_Command:
00661         DBG_DEBUG(GWEN_LOGDOMAIN, "Command received: [%s]", GWEN_Buffer_GetStart(xio->readBuffer));
00662         rv=GWEN_Io_LayerHttp_ParseCommand(io, GWEN_Buffer_GetStart(xio->readBuffer));
00663         if (rv) {
00664           xio->lastReadOutResult=rv;
00665           xio->readRequestIn=NULL;
00666           DBG_INFO(GWEN_LOGDOMAIN,
00667                    "Aborting in read request (reason: %d)",
00668                    xio->lastReadOutResult);
00669           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00670           GWEN_Io_Request_free(rIn);
00671           rIn=NULL;
00672         }
00673         else {
00674           xio->lastHeaderPos=0;
00675           xio->readMode=GWEN_Io_LayerHttp_Mode_Header;
00676         }
00677         GWEN_Buffer_Reset(xio->readBuffer);
00678         break;
00679 
00680       case GWEN_Io_LayerHttp_Mode_Status:
00681         DBG_DEBUG(GWEN_LOGDOMAIN, "Status received: [%s]", GWEN_Buffer_GetStart(xio->readBuffer));
00682         rv=GWEN_Io_LayerHttp_ParseStatus(io, GWEN_Buffer_GetStart(xio->readBuffer));
00683         if (rv) {
00684           xio->lastReadOutResult=rv;
00685           xio->readRequestIn=NULL;
00686           DBG_INFO(GWEN_LOGDOMAIN,
00687                    "Aborting in read request (reason: %d)",
00688                    xio->lastReadOutResult);
00689           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00690           GWEN_Io_Request_free(rIn);
00691           rIn=NULL;
00692         }
00693         else {
00694           xio->lastHeaderPos=0;
00695           xio->readMode=GWEN_Io_LayerHttp_Mode_Header;
00696         }
00697         GWEN_Buffer_Reset(xio->readBuffer);
00698         break;
00699 
00700       case GWEN_Io_LayerHttp_Mode_Header: {
00701         uint32_t i;
00702 
00703         DBG_DEBUG(GWEN_LOGDOMAIN, "Header received: [%s]",
00704                   GWEN_Buffer_GetStart(xio->readBuffer)+xio->lastHeaderPos);
00705         i=GWEN_Buffer_GetUsedBytes(xio->readBuffer);
00706         /* append line feed for header to allow parsing of the different lines */
00707         GWEN_Buffer_AppendByte(xio->readBuffer, 10);
00708         if ((i-xio->lastHeaderPos)==0) {
00709           /* header finished, parse it. NOTE: This function will also determine the next
00710            * readMode and the size of the body (if any) */
00711           DBG_DEBUG(GWEN_LOGDOMAIN, "Parsing header");
00712           rv=GWEN_Io_LayerHttp_ParseHeader(io, GWEN_Buffer_GetStart(xio->readBuffer));
00713           if (rv<0) {
00714             xio->lastReadOutResult=rv;
00715             xio->readRequestIn=NULL;
00716             DBG_INFO(GWEN_LOGDOMAIN,
00717                      "Aborting in read request (reason: %d)",
00718                      xio->lastReadOutResult);
00719             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00720             GWEN_Io_Request_free(rIn);
00721             rIn=NULL;
00722           }
00723           GWEN_Buffer_Reset(xio->readBuffer);
00724         }
00725         else {
00726           DBG_DEBUG(GWEN_LOGDOMAIN, "Awaiting next header");
00727           xio->lastHeaderPos=i+1; /* count the added #10 */
00728           if (xio->readRequestOut==NULL) {
00729             if (xio->lastReadOutResult) {
00730               xio->readRequestIn=NULL;
00731               DBG_INFO(GWEN_LOGDOMAIN,
00732                        "Aborting in read request (reason: %d)",
00733                        xio->lastReadOutResult);
00734               GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00735               GWEN_Io_Request_free(rIn);
00736               rIn=NULL;
00737               doneSomething=1;
00738             }
00739             else {
00740               /* read the next header line */
00741               rv=GWEN_Buffer_AllocRoom(xio->readBuffer, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00742               if (rv<0) {
00743                 xio->readRequestIn=NULL;
00744                 xio->lastReadOutResult=GWEN_ERROR_MEMORY_FULL;
00745                 DBG_INFO(GWEN_LOGDOMAIN,
00746                          "Aborting in read request (reason: %d)",
00747                          xio->lastReadOutResult);
00748                 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_MEMORY_FULL);
00749                 GWEN_Io_Request_free(rIn);
00750                 rIn=NULL;
00751                 doneSomething=1;
00752               }
00753               else {
00754                 GWEN_IO_REQUEST *rOut;
00755 
00756                 DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d header bytes", GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00757                 rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00758                                          (uint8_t*)GWEN_Buffer_GetPosPointer(xio->readBuffer),
00759                                          GWEN_IO_LAYER_HTTP_LINE_STEPSIZE,
00760                                          NULL, NULL,
00761                                          GWEN_Io_Request_GetGuiId(rIn));
00762                 rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00763                 if (rv) {
00764                   if (rv!=GWEN_ERROR_TRY_AGAIN) {
00765                     GWEN_Io_Request_free(rOut);
00766                     xio->readRequestIn=NULL;
00767                     xio->lastReadOutResult=rv;
00768                     DBG_INFO(GWEN_LOGDOMAIN,
00769                              "Aborting in read request (reason: %d)",
00770                              xio->lastReadOutResult);
00771                     GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00772                     GWEN_Io_Request_free(rIn);
00773                     rIn=NULL;
00774                     doneSomething=1;
00775                   }
00776                 }
00777                 else {
00778                   DBG_DEBUG(GWEN_LOGDOMAIN, "Added header read request");
00779                   xio->readRequestOut=rOut;
00780                   doneSomething=1;
00781                 }
00782               } /* if allocRoom succeeded */
00783             }
00784           } /* if no readRequestOut */
00785         }
00786         break;
00787       }
00788 
00789       case GWEN_Io_LayerHttp_Mode_ChunkSize: {
00790         int csize;
00791 
00792         if (GWEN_Buffer_GetUsedBytes(xio->readBuffer)==0) {
00793           DBG_INFO(GWEN_LOGDOMAIN, "Empty line, skipping");
00794         }
00795         else {
00796           if (1!=sscanf(GWEN_Buffer_GetStart(xio->readBuffer), "%x", &csize)) {
00797             DBG_INFO(GWEN_LOGDOMAIN, "Invalid chunksize [%s]", GWEN_Buffer_GetStart(xio->readBuffer));
00798             xio->lastReadOutResult=GWEN_ERROR_BAD_DATA;
00799             xio->readRequestIn=NULL;
00800             DBG_INFO(GWEN_LOGDOMAIN,
00801                      "Aborting in read request (reason: %d)",
00802                      xio->lastReadOutResult);
00803             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_DATA);
00804             GWEN_Io_Request_free(rIn);
00805             rIn=NULL;
00806           }
00807           else {
00808             xio->currentReadChunkSize=csize;
00809             DBG_DEBUG(GWEN_LOGDOMAIN, "Chunksize: %d", csize);
00810             if (csize==0) {
00811               DBG_DEBUG(GWEN_LOGDOMAIN, "Last chunk received");
00812               xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00813               GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00814             }
00815             else {
00816               DBG_DEBUG(GWEN_LOGDOMAIN, "Started reading next chunk (%d bytes)",
00817                         csize);
00818               xio->readMode=GWEN_Io_LayerHttp_Mode_Chunk;
00819             }
00820           }
00821         }
00822         break;
00823       }
00824 
00825       default:
00826         /* should never reach this point */
00827         assert(0);
00828         break;
00829       }
00830     } /* if line finished */
00831   } /* if readRequestIn */
00832 
00833   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00834 }
00835 
00836 
00837 
00838 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest2(GWEN_IO_LAYER *io) {
00839   GWEN_IO_LAYER_HTTP *xio;
00840   int doneSomething=0;
00841 
00842   assert(io);
00843   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00844   assert(xio);
00845 
00846   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest2 (%d)", xio->readMode);
00847 
00848   if (xio->readRequestOut) {
00849     /* check for finished outbound read request */
00850     if (GWEN_Io_Request_GetStatus(xio->readRequestOut)==GWEN_Io_Request_StatusFinished) {
00851       GWEN_IO_REQUEST *rOut;
00852       uint32_t bposOut;
00853       uint32_t flagsOut;
00854 
00855       rOut=xio->readRequestOut;
00856       flagsOut=GWEN_Io_Request_GetFlags(rOut);
00857       bposOut=GWEN_Io_Request_GetBufferPos(rOut);
00858 
00859       doneSomething=1;
00860 
00861       if (xio->readRequestIn) {
00862         GWEN_IO_REQUEST *rIn;
00863         uint32_t bposIn;
00864         uint32_t flagsIn;
00865 
00866         rIn=xio->readRequestIn;
00867         flagsIn=GWEN_Io_Request_GetFlags(rIn);
00868         bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00869 
00870         DBG_VERBOUS(GWEN_LOGDOMAIN, "Received %d (total: %d) bytes", bposIn, bposIn+bposOut);
00871 
00872         /* get all available data */
00873         xio->lastReadOutResult=GWEN_Io_Request_GetResultCode(xio->readRequestOut);
00874 
00875         /* delete outbound request */
00876         GWEN_Io_Request_free(xio->readRequestOut);
00877         xio->readRequestOut=NULL;
00878 
00879         /* advance point in incoming buffer by amount of data read */
00880         bposIn+=bposOut;
00881         GWEN_Io_Request_SetBufferPos(rIn, bposIn);
00882         /* decrease number of bytes to read for body */
00883         if (xio->currentReadBodySize!=-1) {
00884           xio->currentReadBodySize-=bposOut;
00885         }
00886         /* decrease number of bytes to read for chunk (if any) */
00887         if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk) {
00888           xio->currentReadChunkSize-=bposOut;
00889         }
00890         /* check whether the body has been finished */
00891         if (xio->currentReadBodySize==0) {
00892           /* body finished (in any mode) */
00893           GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00894           xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00895         }
00896         else {
00897           if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk && xio->currentReadChunkSize==0) {
00898             /* chunk finished, next step is to read the size of the next chunk */
00899             DBG_DEBUG(GWEN_LOGDOMAIN, "Chunk finished");
00900             xio->currentReadChunkSize=-1;
00901             xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
00902             xio->readLineFinished=0;
00903             GWEN_Buffer_Reset(xio->readBuffer);
00904             doneSomething=1;
00905           }
00906         }
00907       }
00908     }
00909   }
00910 
00911   if (xio->readRequestIn) {
00912     GWEN_IO_REQUEST *rIn;
00913     uint32_t flagsIn;
00914 
00915     rIn=xio->readRequestIn;
00916     flagsIn=GWEN_Io_Request_GetFlags(rIn);
00917 
00918     if (xio->readMode==GWEN_Io_LayerHttp_Mode_Finished) {
00919       uint32_t bposIn;
00920 
00921       GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00922       bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00923       if (bposIn<GWEN_Io_Request_GetBufferSize(rIn) &&
00924           (flagsIn & GWEN_IO_REQUEST_FLAGS_READALL)) {
00925         /* fixed size has been given but can't be fulfilled, so return an error here */
00926         xio->readRequestIn=NULL;
00927         DBG_INFO(GWEN_LOGDOMAIN,
00928                  "Aborting in read request (reason: %d)",
00929                  GWEN_ERROR_BAD_SIZE);
00930         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_SIZE);
00931         GWEN_Io_Request_free(rIn);
00932         rIn=NULL;
00933       }
00934       else {
00935         /* request finished */
00936         xio->readRequestIn=NULL;
00937         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
00938         GWEN_Io_Request_free(rIn);
00939         rIn=NULL;
00940       }
00941       xio->readMode=GWEN_Io_LayerHttp_Mode_Idle;
00942       doneSomething=1;
00943     } /* if finished */
00944     else if (xio->readMode==GWEN_Io_LayerHttp_Mode_ChunkSize) {
00945       /* don't enqueue a new request here since we
00946        * just changed into readChunkSize mode */
00947     }
00948     else {
00949       uint32_t len;
00950       uint32_t bposIn;
00951 
00952       bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00953       len=GWEN_Io_Request_GetBufferSize(rIn)-bposIn;
00954       if (len==0) {
00955         /* inbound read request fullfilled */
00956         xio->readRequestIn=NULL;
00957         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
00958         GWEN_Io_Request_free(rIn);
00959         rIn=NULL;
00960         doneSomething=1;
00961       } /* if request fullfilled */
00962       else {
00963         if (xio->readRequestOut==NULL) {
00964           if (xio->lastReadOutResult) {
00965             xio->readRequestIn=NULL;
00966             DBG_INFO(GWEN_LOGDOMAIN,
00967                      "Aborting in read request (reason: %d)",
00968                      xio->lastReadOutResult);
00969             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00970             GWEN_Io_Request_free(rIn);
00971             rIn=NULL;
00972             doneSomething=1;
00973           }
00974           else {
00975             if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk &&
00976                 xio->currentReadChunkSize!=-1 &&
00977                 len>xio->currentReadChunkSize)
00978               len=xio->currentReadChunkSize;
00979             else if (xio->readMode==GWEN_Io_LayerHttp_Mode_Body &&
00980                      xio->currentReadBodySize!=-1 &&
00981                      len>xio->currentReadBodySize)
00982               len=xio->currentReadBodySize;
00983 
00984             if (len) {
00985               GWEN_IO_REQUEST *rOut;
00986               int rv;
00987 
00988               DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d body bytes (already have %d/%d)",
00989                           len, bposIn, GWEN_Io_Request_GetBufferSize(rIn));
00990               rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00991                                        GWEN_Io_Request_GetBufferPtr(rIn)+bposIn, len,
00992                                        NULL, NULL,
00993                                        GWEN_Io_Request_GetGuiId(rIn));
00994               GWEN_Io_Request_AddFlags(rOut, GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW);
00995               rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00996               if (rv) {
00997                 GWEN_Io_Request_free(rOut);
00998                 if (rv!=GWEN_ERROR_TRY_AGAIN) {
00999                   xio->lastReadOutResult=rv;
01000                   xio->readRequestIn=NULL;
01001                   DBG_INFO(GWEN_LOGDOMAIN,
01002                            "Aborting in read request (reason: %d)",
01003                            xio->lastReadOutResult);
01004                   GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01005                   GWEN_Io_Request_free(rIn);
01006                   rIn=NULL;
01007                   doneSomething=1;
01008                 }
01009               }
01010               else {
01011                 xio->readRequestOut=rOut;
01012                 doneSomething=1;
01013               }
01014             } /* no bytes to read */
01015             else {
01016               if (xio->currentReadBodySize==0)
01017                 xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
01018               if (xio->currentReadChunkSize==0) {
01019                 xio->currentReadChunkSize=-1;
01020                 xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
01021               }
01022             }
01023           }
01024         } /* if there is no outbound read request */
01025       } /* if inbound request not yet fullfilled */
01026     } /* if not finished */
01027   } /* if there is an inbound read request */
01028 
01029   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01030 }
01031 
01032 
01033 
01034 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest(GWEN_IO_LAYER *io) {
01035   GWEN_IO_LAYER_HTTP *xio;
01036 
01037   assert(io);
01038   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01039   assert(xio);
01040 
01041   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest (%d)", xio->readMode);
01042 
01043   switch(xio->readMode) {
01044   case GWEN_Io_LayerHttp_Mode_Command:
01045   case GWEN_Io_LayerHttp_Mode_Status:
01046   case GWEN_Io_LayerHttp_Mode_Header:
01047   case GWEN_Io_LayerHttp_Mode_ChunkSize:
01048     return GWEN_Io_LayerHttp_WorkOnReadRequest1(io);
01049 
01050   case GWEN_Io_LayerHttp_Mode_Chunk:
01051   case GWEN_Io_LayerHttp_Mode_Body:
01052   case GWEN_Io_LayerHttp_Mode_Finished:
01053   default:
01054     return GWEN_Io_LayerHttp_WorkOnReadRequest2(io);
01055   }
01056 }
01057 
01058 
01059 
01060 /* writing command/status/header */
01061 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest1(GWEN_IO_LAYER *io) {
01062   GWEN_IO_LAYER_HTTP *xio;
01063   int doneSomething=0;
01064 
01065   assert(io);
01066   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01067   assert(xio);
01068 
01069   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest1 (%d)", xio->writeMode);
01070 
01071   if (xio->writeRequestOut) {
01072     if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
01073       GWEN_IO_REQUEST *rOut;
01074       uint32_t bposOut;
01075       uint32_t flagsOut;
01076 
01077       rOut=xio->writeRequestOut;
01078       flagsOut=GWEN_Io_Request_GetFlags(rOut);
01079       bposOut=GWEN_Io_Request_GetBufferPos(rOut);
01080 
01081       DBG_VERBOUS(GWEN_LOGDOMAIN, "Sent %d bytes", bposOut);
01082 
01083       GWEN_Buffer_IncrementPos(xio->writeBuffer, bposOut);
01084       xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(xio->writeRequestOut);
01085 
01086       /* delete outbound request */
01087       GWEN_Io_Request_free(xio->writeRequestOut);
01088       xio->writeRequestOut=NULL;
01089 
01090       doneSomething=1;
01091     }
01092   }
01093 
01094   if (xio->writeRequestIn) {
01095     GWEN_IO_REQUEST *rIn;
01096 
01097     rIn=xio->writeRequestIn;
01098     if (GWEN_Buffer_GetBytesLeft(xio->writeBuffer)) {
01099       if (xio->writeRequestOut==NULL) {
01100         if (xio->lastWriteOutResult) {
01101           xio->writeRequestIn=NULL;
01102           DBG_INFO(GWEN_LOGDOMAIN,
01103                    "Aborting in write request (reason: %d)",
01104                    xio->lastWriteOutResult);
01105           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastWriteOutResult);
01106           GWEN_Io_Request_free(rIn);
01107           rIn=NULL;
01108           doneSomething=1;
01109         }
01110         else {
01111           GWEN_IO_REQUEST *rOut;
01112           int rv;
01113 
01114           DBG_VERBOUS(GWEN_LOGDOMAIN, "Sending %d header bytes", GWEN_Buffer_GetBytesLeft(xio->writeBuffer));
01115           rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
01116                                    (uint8_t*)GWEN_Buffer_GetPosPointer(xio->writeBuffer),
01117                                    GWEN_Buffer_GetBytesLeft(xio->writeBuffer),
01118                                    NULL, NULL,
01119                                    GWEN_Io_Request_GetGuiId(rIn));
01120           GWEN_Io_Request_AddFlags(rOut,
01121                                    GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW |
01122                                    GWEN_IO_REQUEST_FLAGS_FLUSH |
01123                                    GWEN_IO_REQUEST_FLAGS_WRITEALL);
01124           rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
01125           if (rv) {
01126             GWEN_Io_Request_free(rOut);
01127             if (rv!=GWEN_ERROR_TRY_AGAIN) {
01128               xio->lastWriteOutResult=rv;
01129               xio->writeRequestIn=NULL;
01130               DBG_INFO(GWEN_LOGDOMAIN,
01131                        "Aborting in write request (reason: %d)",
01132                        xio->lastWriteOutResult);
01133               GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01134               GWEN_Io_Request_free(rIn);
01135               rIn=NULL;
01136               doneSomething=1;
01137             }
01138           }
01139           else {
01140             xio->writeRequestOut=rOut;
01141             doneSomething=1;
01142           }
01143         } /* if lastOutResult was ok */
01144       } /* if there is no outbound request */
01145     } /* if there still are bytes in the buffer to write */
01146     else {
01147       /* header finished, prepare writing of the body */
01148       GWEN_Buffer_Reset(xio->writeBuffer);
01149       if (xio->currentWriteBodySize!=0)
01150         /* header finished, body follows */
01151         xio->writeMode=GWEN_Io_LayerHttp_Mode_Body;
01152       else
01153         /* no body */
01154         xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01155     }
01156   } /* if there is an inbound request */
01157 
01158 
01159   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01160 }
01161 
01162 
01163 
01164 /* writing body/ finished*/
01165 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest2(GWEN_IO_LAYER *io) {
01166   GWEN_IO_LAYER_HTTP *xio;
01167   int doneSomething=0;
01168 
01169   assert(io);
01170   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01171   assert(xio);
01172 
01173   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest2 (%d)", xio->writeMode);
01174 
01175   if (xio->writeRequestOut) {
01176     if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
01177       GWEN_IO_REQUEST *rOut;
01178 
01179       doneSomething=1;
01180       rOut=xio->writeRequestOut;
01181       if (xio->writeRequestIn) {
01182         uint32_t bposOut;
01183         uint32_t flagsOut;
01184         GWEN_IO_REQUEST *rIn;
01185         uint32_t bposIn;
01186         uint32_t flagsIn;
01187 
01188         rOut=xio->writeRequestOut;
01189         flagsOut=GWEN_Io_Request_GetFlags(rOut);
01190         bposOut=GWEN_Io_Request_GetBufferPos(rOut);
01191 
01192         rIn=xio->writeRequestIn;
01193         flagsIn=GWEN_Io_Request_GetFlags(rIn);
01194         bposIn=GWEN_Io_Request_GetBufferPos(rIn)+bposOut;
01195         GWEN_Io_Request_SetBufferPos(rIn, bposIn);
01196 
01197         DBG_VERBOUS(GWEN_LOGDOMAIN, "Sent %d body bytes (%d)",
01198                     bposOut, GWEN_Io_Request_GetResultCode(rOut));
01199 
01200         /* get last result */
01201         xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(rOut);
01202 
01203         /* delete outbound request */
01204         GWEN_Io_Request_free(xio->writeRequestOut);
01205         xio->writeRequestOut=NULL;
01206 
01207         if (xio->currentWriteBodySize!=-1)
01208           xio->currentWriteBodySize-=bposOut;
01209 
01210         /* check whether the body has been finished */
01211         if (xio->currentWriteBodySize==0) {
01212           /* body finished (in any mode) */
01213           GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
01214           xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01215           if (bposIn<GWEN_Io_Request_GetBufferSize(rIn) &&
01216               (flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL)) {
01217             /* body finished, but caller insists on writing more data, abort */
01218             xio->writeRequestIn=NULL;
01219             DBG_INFO(GWEN_LOGDOMAIN,
01220                      "Aborting in write request (reason: %d)",
01221                      GWEN_ERROR_BAD_SIZE);
01222             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_SIZE);
01223             GWEN_Io_Request_free(rIn);
01224             rIn=NULL;
01225           }
01226         }
01227         else {
01228           /* body not complete (or unknown) */
01229           if (bposIn>=GWEN_Io_Request_GetBufferSize(rIn) ||
01230               (bposIn && !(flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL))) {
01231             /* inbound request fullfilled */
01232             xio->writeRequestIn=NULL;
01233             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
01234             GWEN_Io_Request_free(rIn);
01235             rIn=NULL;
01236           }
01237         }
01238       }
01239     }
01240   }
01241 
01242   if (xio->writeRequestIn) {
01243     GWEN_IO_REQUEST *rIn;
01244 
01245     rIn=xio->writeRequestIn;
01246     if (xio->writeRequestOut==NULL) {
01247       if (xio->lastWriteOutResult) {
01248         xio->writeRequestIn=NULL;
01249         DBG_INFO(GWEN_LOGDOMAIN,
01250                  "Aborting in write request (reason: %d)",
01251                  xio->lastWriteOutResult);
01252         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastWriteOutResult);
01253         GWEN_Io_Request_free(rIn);
01254         rIn=NULL;
01255         doneSomething=1;
01256       }
01257       else {
01258         int len;
01259         int bpos;
01260 
01261         /* create new write request for remaining bytes */
01262         bpos=GWEN_Io_Request_GetBufferPos(rIn);
01263         len=GWEN_Io_Request_GetBufferSize(rIn)-bpos;
01264         if (xio->currentWriteBodySize!=-1 && len>xio->currentWriteBodySize)
01265           /* adapt number of bytes to write */
01266           len=xio->currentWriteBodySize;
01267 
01268         if (len==0) {
01269           if (xio->currentWriteBodySize==0)
01270             GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
01271           xio->writeRequestIn=NULL;
01272           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
01273           GWEN_Io_Request_free(rIn);
01274           rIn=NULL;
01275           doneSomething=1;
01276         }
01277         else {
01278           GWEN_IO_REQUEST *rOut;
01279           int rv;
01280 
01281           /* create new write request for remaining bytes */
01282           DBG_VERBOUS(GWEN_LOGDOMAIN, "Sending %d body bytes", len);
01283           rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
01284                                    GWEN_Io_Request_GetBufferPtr(rIn)+bpos, len,
01285                                    NULL, NULL,
01286                                    GWEN_Io_Request_GetGuiId(rIn));
01287           GWEN_Io_Request_AddFlags(rOut,
01288                                    GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW |
01289                                    GWEN_IO_REQUEST_FLAGS_FLUSH |
01290                                    GWEN_IO_REQUEST_FLAGS_WRITEALL);
01291           rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
01292           if (rv) {
01293             GWEN_Io_Request_free(rOut);
01294             if (rv!=GWEN_ERROR_TRY_AGAIN) {
01295               xio->lastWriteOutResult=rv;
01296               xio->writeRequestIn=NULL;
01297               DBG_INFO(GWEN_LOGDOMAIN,
01298                        "Aborting in write request (reason: %d)",
01299                        xio->lastWriteOutResult);
01300               GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01301               GWEN_Io_Request_free(rIn);
01302               rIn=NULL;
01303               doneSomething=1;
01304             }
01305           }
01306           else {
01307             xio->writeRequestOut=rOut;
01308             doneSomething=1;
01309           }
01310         }
01311       } /* if lastOutResult was ok */
01312     }
01313 
01314 
01315   } /* if there is an inbound request */
01316 
01317 
01318   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01319 }
01320 
01321 
01322 
01323 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest(GWEN_IO_LAYER *io) {
01324   GWEN_IO_LAYER_HTTP *xio;
01325 
01326   assert(io);
01327   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01328   assert(xio);
01329 
01330   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest (%d)", xio->writeMode);
01331 
01332   switch(xio->writeMode) {
01333   case GWEN_Io_LayerHttp_Mode_Command:
01334   case GWEN_Io_LayerHttp_Mode_Status:
01335   case GWEN_Io_LayerHttp_Mode_Header:
01336   case GWEN_Io_LayerHttp_Mode_ChunkSize:
01337     return GWEN_Io_LayerHttp_WorkOnWriteRequest1(io);
01338 
01339   case GWEN_Io_LayerHttp_Mode_Chunk:
01340   case GWEN_Io_LayerHttp_Mode_Body:
01341   case GWEN_Io_LayerHttp_Mode_Finished:
01342   default:
01343     return GWEN_Io_LayerHttp_WorkOnWriteRequest2(io);
01344   }
01345 }
01346 
01347 
01348 
01349 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnRequests(GWEN_IO_LAYER *io) {
01350   GWEN_IO_LAYER_HTTP *xio;
01351   int doneSomething=0;
01352 
01353   assert(io);
01354   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01355   assert(xio);
01356 
01357   /* work on read request */
01358   if (GWEN_Io_LayerHttp_WorkOnReadRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01359     doneSomething=1;
01360 
01361   /* work on write request */
01362   if (GWEN_Io_LayerHttp_WorkOnWriteRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01363     doneSomething=1;
01364 
01365   /* let base layer work */
01366   if (GWEN_Io_Layer_WorkOnRequests(GWEN_Io_Layer_GetBaseLayer(io))!=GWEN_Io_Layer_WorkResultBlocking)
01367     doneSomething=1;
01368 
01369   if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
01370     GWEN_IO_LAYER *newIo;
01371 
01372     newIo=GWEN_Io_Layer_GetNextIncomingLayer(GWEN_Io_Layer_GetBaseLayer(io));
01373     if (newIo) {
01374       GWEN_IO_LAYER *newNewIo;
01375       GWEN_DB_NODE *dbSrc;
01376       GWEN_DB_NODE *dbDst;
01377       uint32_t fl;
01378 
01379       fl=GWEN_Io_Layer_GetFlags(io);
01380       newNewIo=GWEN_Io_LayerHttp_new(newIo);
01381       GWEN_Io_Layer_AddFlags(newNewIo, GWEN_IO_LAYER_FLAGS_PASSIVE);
01382       GWEN_Io_Layer_AddFlags(newNewIo, fl & 0xffff);
01383       /* copy command */
01384       dbDst=GWEN_Io_LayerHttp_GetDbCommandOut(newNewIo);
01385       dbSrc=xio->dbCommandOut;
01386       GWEN_DB_AddGroupChildren(dbDst, dbSrc);
01387 
01388       GWEN_Io_Layer_AddIncomingLayer(io, newNewIo);
01389       doneSomething=1;
01390     }
01391   }
01392 
01393   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01394 }
01395 
01396 
01397 
01398 
01399 int GWEN_Io_LayerHttp_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01400   GWEN_IO_LAYER_HTTP *xio;
01401   GWEN_IO_LAYER_STATUS st;
01402   uint32_t lflags;
01403   uint32_t rflags;
01404 
01405   assert(io);
01406   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01407   assert(xio);
01408 
01409   st=GWEN_Io_Layer_GetStatus(io);
01410   lflags=GWEN_Io_Layer_GetFlags(io);
01411   rflags=GWEN_Io_Request_GetFlags(r);
01412 
01413   switch(GWEN_Io_Request_GetType(r)) {
01414   case GWEN_Io_Request_TypeRead:
01415     /* check status */
01416     if (st!=GWEN_Io_Layer_StatusConnected) {
01417       DBG_INFO(GWEN_LOGDOMAIN, "Layer not connected (%d)", st);
01418       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01419       return GWEN_ERROR_NOT_OPEN;
01420     }
01421 
01422     if (xio->lastReadOutResult) {
01423       DBG_INFO(GWEN_LOGDOMAIN, "Unable to read (%d)", xio->lastReadOutResult);
01424       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
01425       return xio->lastReadOutResult;
01426     }
01427 
01428     /* check whether we already have a read request */
01429     if (xio->readRequestIn) {
01430       DBG_INFO(GWEN_LOGDOMAIN, "There already is a read request");
01431       return GWEN_ERROR_TRY_AGAIN;
01432     }
01433 
01434     if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETBEGIN) {
01435       if (xio->readMode!=GWEN_Io_LayerHttp_Mode_Idle) {
01436         DBG_INFO(GWEN_LOGDOMAIN, "Packetbegin requested while there is still a packet in work");
01437         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01438         return GWEN_ERROR_INVALID;
01439       }
01440 
01441       GWEN_Buffer_Reset(xio->readBuffer);
01442       GWEN_DB_ClearGroup(xio->dbCommandIn, NULL);
01443       GWEN_DB_ClearGroup(xio->dbStatusIn, NULL);
01444       GWEN_DB_ClearGroup(xio->dbHeaderIn, NULL);
01445       xio->currentReadChunkSize=-1;
01446       xio->currentReadBodySize=-1;
01447       xio->readLineFinished=0;
01448       if ((lflags & GWEN_IO_LAYER_HTTP_FLAGS_IPC) ||
01449           (lflags & GWEN_IO_LAYER_FLAGS_PASSIVE))
01450         xio->readMode=GWEN_Io_LayerHttp_Mode_Command;
01451       else
01452         xio->readMode=GWEN_Io_LayerHttp_Mode_Status;
01453     }
01454     else {
01455       if (xio->readMode!=GWEN_Io_LayerHttp_Mode_ChunkSize &&
01456           xio->readMode!=GWEN_Io_LayerHttp_Mode_Chunk &&
01457           xio->readMode!=GWEN_Io_LayerHttp_Mode_Body) {
01458         DBG_INFO(GWEN_LOGDOMAIN, "Bad read mode and flag GWEN_IO_REQUEST_FLAGS_PACKETBEGIN not set");
01459         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01460         return GWEN_ERROR_INVALID;
01461       }
01462     }
01463 
01464     /* enqueue request */
01465     xio->readRequestIn=r;
01466     GWEN_Io_Request_Attach(xio->readRequestIn);
01467     break;
01468 
01469   case GWEN_Io_Request_TypeWrite:
01470     /* check status */
01471     if (st!=GWEN_Io_Layer_StatusConnected) {
01472       DBG_INFO(GWEN_LOGDOMAIN, "Layer is not connected");
01473       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01474       return GWEN_ERROR_NOT_OPEN;
01475     }
01476 
01477     /* check whether we already have a read request */
01478     if (xio->writeRequestIn) {
01479       DBG_INFO(GWEN_LOGDOMAIN, "There already is a write request");
01480       return GWEN_ERROR_TRY_AGAIN;
01481     }
01482 
01483     if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETBEGIN) {
01484       int rv;
01485 
01486       if (xio->writeMode!=GWEN_Io_LayerHttp_Mode_Idle && xio->writeMode!=GWEN_Io_LayerHttp_Mode_Finished) {
01487         DBG_INFO(GWEN_LOGDOMAIN, "Packetbegin requested while there is still a packet in work");
01488         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01489         return GWEN_ERROR_INVALID;
01490       }
01491 
01492       DBG_VERBOUS(GWEN_LOGDOMAIN, "Packet begin");
01493       GWEN_Buffer_Reset(xio->writeBuffer);
01494       /* Write command/status */
01495       if ((lflags & GWEN_IO_LAYER_HTTP_FLAGS_IPC) ||
01496           !(lflags & GWEN_IO_LAYER_FLAGS_PASSIVE)) {
01497         rv=GWEN_Io_LayerHttp_WriteCommand(io, xio->writeBuffer);
01498         xio->writeMode=GWEN_Io_LayerHttp_Mode_Command;
01499       }
01500       else {
01501         rv=GWEN_Io_LayerHttp_WriteStatus(io, xio->writeBuffer);
01502         xio->writeMode=GWEN_Io_LayerHttp_Mode_Status;
01503       }
01504       if (rv<0) {
01505         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01506         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
01507         xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01508         return rv;
01509       }
01510 
01511       if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETEND)
01512         /* both flags packet begin and end are given, so we already know the content-length */
01513         GWEN_DB_SetIntValue(xio->dbHeaderOut, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-length",
01514                             GWEN_Io_Request_GetBufferSize(r));
01515 
01516       /* write header into buffer, get body size */
01517       rv=GWEN_Io_LayerHttp_WriteHeader(io, xio->writeBuffer);
01518       if (rv<0) {
01519         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01520         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
01521         xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01522         return rv;
01523       }
01524       GWEN_Buffer_Rewind(xio->writeBuffer);
01525       xio->writeMode=GWEN_Io_LayerHttp_Mode_Header;
01526       DBG_VERBOUS(GWEN_LOGDOMAIN, "Buffer: %d/%d",
01527                   GWEN_Buffer_GetBytesLeft(xio->writeBuffer),
01528                   GWEN_Buffer_GetUsedBytes(xio->writeBuffer));
01529     }
01530     else {
01531       if (xio->writeMode!=GWEN_Io_LayerHttp_Mode_Body) {
01532         if ((GWEN_Io_Request_GetBufferSize(r)==0) &&
01533             (rflags & GWEN_IO_REQUEST_FLAGS_FLUSH)) {
01534           /* this is just a flush request */
01535           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01536           return 0;
01537         }
01538         else {
01539           DBG_INFO(GWEN_LOGDOMAIN, "Bad write mode and flag GWEN_IO_REQUEST_FLAGS_PACKETBEGIN not set");
01540           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01541           return GWEN_ERROR_INVALID;
01542         }
01543       }
01544     }
01545 
01546     /* enqueue request */
01547     xio->writeRequestIn=r;
01548     GWEN_Io_Request_Attach(xio->writeRequestIn);
01549     break;
01550 
01551   case GWEN_Io_Request_TypeConnect:
01552     /* check status */
01553     if (st!=GWEN_Io_Layer_StatusUnconnected &&
01554         st!=GWEN_Io_Layer_StatusDisconnected) {
01555       DBG_INFO(GWEN_LOGDOMAIN, "Layer not un-/disconnected");
01556       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01557       return GWEN_ERROR_NOT_OPEN;
01558     }
01559     else {
01560       /* reset all structures */
01561       xio->lastReadOutResult=0;
01562       GWEN_Buffer_Reset(xio->readBuffer);
01563       xio->readMode=GWEN_Io_LayerHttp_Mode_Idle;
01564       xio->currentReadChunkSize=-1;
01565       xio->currentReadBodySize=-1;
01566       xio->readLineFinished=0;
01567 
01568       xio->lastWriteOutResult=0;
01569       GWEN_Buffer_Reset(xio->writeBuffer);
01570       xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01571 
01572       GWEN_DB_ClearGroup(xio->dbCommandIn, NULL);
01573       GWEN_DB_ClearGroup(xio->dbStatusIn, NULL);
01574       GWEN_DB_ClearGroup(xio->dbHeaderIn, NULL);
01575 
01576       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
01577       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01578       DBG_INFO(GWEN_LOGDOMAIN, "Layer now connected");
01579     }
01580     break;
01581 
01582   case GWEN_Io_Request_TypeDisconnect:
01583     /* check status */
01584     if (st!=GWEN_Io_Layer_StatusConnected) {
01585       DBG_INFO(GWEN_LOGDOMAIN, "IO layer is not open");
01586       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01587       return GWEN_ERROR_NOT_OPEN;
01588     }
01589     else {
01590       /* abort incoming requests, if any */
01591       GWEN_Io_LayerHttp_AbortInRequests(io, GWEN_ERROR_ABORTED);
01592       GWEN_Io_LayerHttp_AbortOutRequests(io);
01593 
01594       /* closed */
01595       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01596       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01597     }
01598     break;
01599 
01600   default:
01601     DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
01602     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
01603     return GWEN_ERROR_NOT_SUPPORTED;
01604   }
01605 
01606   return 0;
01607 }
01608 
01609 
01610 
01611 int GWEN_Io_LayerHttp_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01612   GWEN_IO_LAYER_HTTP *xio;
01613 
01614   assert(io);
01615   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01616   assert(xio);
01617 
01618   switch(GWEN_Io_Request_GetType(r)) {
01619   case GWEN_Io_Request_TypeRead:
01620     if (xio->readRequestIn==r) {
01621       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted read request");
01622       xio->readRequestIn=NULL;
01623       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01624       GWEN_Io_Request_free(r);
01625     }
01626     else {
01627       /* not my request */
01628       DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
01629       return GWEN_ERROR_INVALID;
01630     }
01631     break;
01632 
01633   case GWEN_Io_Request_TypeWrite:
01634     if (xio->writeRequestIn==r) {
01635       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted write request");
01636       xio->writeRequestIn=NULL;
01637       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01638       GWEN_Io_Request_free(r);
01639     }
01640     else {
01641       /* not my request */
01642       DBG_INFO(GWEN_LOGDOMAIN, "Write request not registered with this io layer");
01643       return GWEN_ERROR_INVALID;
01644     }
01645     break;
01646 
01647   default:
01648     break;
01649   }
01650 
01651   return 0;
01652 }
01653 
01654 
01655 
01656 int GWEN_Io_LayerHttp_HasWaitingRequests(GWEN_IO_LAYER *io) {
01657   GWEN_IO_LAYER_HTTP *xio;
01658 
01659   assert(io);
01660   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01661   assert(xio);
01662 
01663   if (xio->readRequestIn || xio->writeRequestIn)
01664     return 1;
01665   else
01666     return 0;
01667 }
01668 
01669 
01670 
01671 
01672 
01673 

Generated on Sat Jan 2 09:32:35 2010 for gwenhywfar by  doxygen 1.6.1