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(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             int rv;
00730 
00731             if (xio->lastReadOutResult) {
00732               xio->readRequestIn=NULL;
00733               DBG_INFO(GWEN_LOGDOMAIN,
00734                        "Aborting in read request (reason: %d)",
00735                        xio->lastReadOutResult);
00736               GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00737               GWEN_Io_Request_free(rIn);
00738               rIn=NULL;
00739               doneSomething=1;
00740             }
00741             else {
00742               /* read the next header line */
00743               rv=GWEN_Buffer_AllocRoom(xio->readBuffer, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00744               if (rv<0) {
00745                 xio->readRequestIn=NULL;
00746                 xio->lastReadOutResult=GWEN_ERROR_MEMORY_FULL;
00747                 DBG_INFO(GWEN_LOGDOMAIN,
00748                          "Aborting in read request (reason: %d)",
00749                          xio->lastReadOutResult);
00750                 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_MEMORY_FULL);
00751                 GWEN_Io_Request_free(rIn);
00752                 rIn=NULL;
00753                 doneSomething=1;
00754               }
00755               else {
00756                 GWEN_IO_REQUEST *rOut;
00757 
00758                 DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d header bytes", GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00759                 rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00760                                          (uint8_t*)GWEN_Buffer_GetPosPointer(xio->readBuffer),
00761                                          GWEN_IO_LAYER_HTTP_LINE_STEPSIZE,
00762                                          NULL, NULL,
00763                                          GWEN_Io_Request_GetGuiId(rIn));
00764                 rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00765                 if (rv) {
00766                   if (rv!=GWEN_ERROR_TRY_AGAIN) {
00767                     GWEN_Io_Request_free(rOut);
00768                     xio->readRequestIn=NULL;
00769                     xio->lastReadOutResult=rv;
00770                     DBG_INFO(GWEN_LOGDOMAIN,
00771                              "Aborting in read request (reason: %d)",
00772                              xio->lastReadOutResult);
00773                     GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00774                     GWEN_Io_Request_free(rIn);
00775                     rIn=NULL;
00776                     doneSomething=1;
00777                   }
00778                 }
00779                 else {
00780                   DBG_DEBUG(GWEN_LOGDOMAIN, "Added header read request");
00781                   xio->readRequestOut=rOut;
00782                   doneSomething=1;
00783                 }
00784               } /* if allocRoom succeeded */
00785             }
00786           } /* if no readRequestOut */
00787         }
00788         break;
00789       }
00790 
00791       case GWEN_Io_LayerHttp_Mode_ChunkSize: {
00792         int csize;
00793 
00794         if (GWEN_Buffer_GetUsedBytes(xio->readBuffer)==0) {
00795           DBG_INFO(GWEN_LOGDOMAIN, "Empty line, skipping");
00796         }
00797         else {
00798           if (1!=sscanf(GWEN_Buffer_GetStart(xio->readBuffer), "%x", &csize)) {
00799             DBG_INFO(GWEN_LOGDOMAIN, "Invalid chunksize [%s]", GWEN_Buffer_GetStart(xio->readBuffer));
00800             xio->lastReadOutResult=GWEN_ERROR_BAD_DATA;
00801             xio->readRequestIn=NULL;
00802             DBG_INFO(GWEN_LOGDOMAIN,
00803                      "Aborting in read request (reason: %d)",
00804                      xio->lastReadOutResult);
00805             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_DATA);
00806             GWEN_Io_Request_free(rIn);
00807             rIn=NULL;
00808           }
00809           else {
00810             xio->currentReadChunkSize=csize;
00811             DBG_DEBUG(GWEN_LOGDOMAIN, "Chunksize: %d", csize);
00812             if (csize==0) {
00813               DBG_DEBUG(GWEN_LOGDOMAIN, "Last chunk received");
00814               xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00815               GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00816             }
00817             else {
00818               DBG_DEBUG(GWEN_LOGDOMAIN, "Started reading next chunk (%d bytes)",
00819                         csize);
00820               xio->readMode=GWEN_Io_LayerHttp_Mode_Chunk;
00821             }
00822           }
00823         }
00824         break;
00825       }
00826 
00827       default:
00828         /* should never reach this point */
00829         assert(0);
00830         break;
00831       }
00832     } /* if line finished */
00833   } /* if readRequestIn */
00834 
00835   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00836 }
00837 
00838 
00839 
00840 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest2(GWEN_IO_LAYER *io) {
00841   GWEN_IO_LAYER_HTTP *xio;
00842   int doneSomething=0;
00843 
00844   assert(io);
00845   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00846   assert(xio);
00847 
00848   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest2 (%d)", xio->readMode);
00849 
00850   if (xio->readRequestOut) {
00851     /* check for finished outbound read request */
00852     if (GWEN_Io_Request_GetStatus(xio->readRequestOut)==GWEN_Io_Request_StatusFinished) {
00853       GWEN_IO_REQUEST *rOut;
00854       uint32_t bposOut;
00855       uint32_t flagsOut;
00856 
00857       rOut=xio->readRequestOut;
00858       flagsOut=GWEN_Io_Request_GetFlags(rOut);
00859       bposOut=GWEN_Io_Request_GetBufferPos(rOut);
00860 
00861       doneSomething=1;
00862 
00863       if (xio->readRequestIn) {
00864         GWEN_IO_REQUEST *rIn;
00865         uint32_t bposIn;
00866         uint32_t flagsIn;
00867 
00868         rIn=xio->readRequestIn;
00869         flagsIn=GWEN_Io_Request_GetFlags(rIn);
00870         bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00871 
00872         DBG_VERBOUS(GWEN_LOGDOMAIN, "Received %d (total: %d) bytes", bposIn, bposIn+bposOut);
00873 
00874         /* get all available data */
00875         xio->lastReadOutResult=GWEN_Io_Request_GetResultCode(xio->readRequestOut);
00876 
00877         /* delete outbound request */
00878         GWEN_Io_Request_free(xio->readRequestOut);
00879         xio->readRequestOut=NULL;
00880 
00881         /* advance point in incoming buffer by amount of data read */
00882         bposIn+=bposOut;
00883         GWEN_Io_Request_SetBufferPos(rIn, bposIn);
00884         /* decrease number of bytes to read for body */
00885         if (xio->currentReadBodySize!=-1) {
00886           xio->currentReadBodySize-=bposOut;
00887         }
00888         /* decrease number of bytes to read for chunk (if any) */
00889         if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk) {
00890           xio->currentReadChunkSize-=bposOut;
00891         }
00892         /* check whether the body has been finished */
00893         if (xio->currentReadBodySize==0) {
00894           /* body finished (in any mode) */
00895           GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00896           xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00897         }
00898         else {
00899           if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk && xio->currentReadChunkSize==0) {
00900             /* chunk finished, next step is to read the size of the next chunk */
00901             DBG_DEBUG(GWEN_LOGDOMAIN, "Chunk finished");
00902             xio->currentReadChunkSize=-1;
00903             xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
00904             xio->readLineFinished=0;
00905             GWEN_Buffer_Reset(xio->readBuffer);
00906             doneSomething=1;
00907           }
00908         }
00909       }
00910     }
00911   }
00912 
00913   if (xio->readRequestIn) {
00914     GWEN_IO_REQUEST *rIn;
00915     uint32_t flagsIn;
00916 
00917     rIn=xio->readRequestIn;
00918     flagsIn=GWEN_Io_Request_GetFlags(rIn);
00919 
00920     if (xio->readMode==GWEN_Io_LayerHttp_Mode_Finished) {
00921       uint32_t bposIn;
00922 
00923       GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00924       bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00925       if (bposIn<GWEN_Io_Request_GetBufferSize(rIn) &&
00926           (flagsIn & GWEN_IO_REQUEST_FLAGS_READALL)) {
00927         /* fixed size has been given but can't be fulfilled, so return an error here */
00928         xio->readRequestIn=NULL;
00929         DBG_INFO(GWEN_LOGDOMAIN,
00930                  "Aborting in read request (reason: %d)",
00931                  GWEN_ERROR_BAD_SIZE);
00932         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_SIZE);
00933         GWEN_Io_Request_free(rIn);
00934         rIn=NULL;
00935       }
00936       else {
00937         /* request finished */
00938         xio->readRequestIn=NULL;
00939         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
00940         GWEN_Io_Request_free(rIn);
00941         rIn=NULL;
00942       }
00943       xio->readMode=GWEN_Io_LayerHttp_Mode_Idle;
00944       doneSomething=1;
00945     } /* if finished */
00946     else if (xio->readMode==GWEN_Io_LayerHttp_Mode_ChunkSize) {
00947       /* don't enqueue a new request here since we
00948        * just changed into readChunkSize mode */
00949     }
00950     else {
00951       uint32_t len;
00952       uint32_t bposIn;
00953 
00954       bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00955       len=GWEN_Io_Request_GetBufferSize(rIn)-bposIn;
00956       if (len==0) {
00957         /* inbound read request fullfilled */
00958         xio->readRequestIn=NULL;
00959         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
00960         GWEN_Io_Request_free(rIn);
00961         rIn=NULL;
00962         doneSomething=1;
00963       } /* if request fullfilled */
00964       else {
00965         if (xio->readRequestOut==NULL) {
00966           if (xio->lastReadOutResult) {
00967             xio->readRequestIn=NULL;
00968             DBG_INFO(GWEN_LOGDOMAIN,
00969                      "Aborting in read request (reason: %d)",
00970                      xio->lastReadOutResult);
00971             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00972             GWEN_Io_Request_free(rIn);
00973             rIn=NULL;
00974             doneSomething=1;
00975           }
00976           else {
00977             if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk &&
00978                 xio->currentReadChunkSize!=-1 &&
00979                 len>xio->currentReadChunkSize)
00980               len=xio->currentReadChunkSize;
00981             else if (xio->readMode==GWEN_Io_LayerHttp_Mode_Body &&
00982                      xio->currentReadBodySize!=-1 &&
00983                      len>xio->currentReadBodySize)
00984               len=xio->currentReadBodySize;
00985 
00986             if (len) {
00987               GWEN_IO_REQUEST *rOut;
00988               int rv;
00989 
00990               DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d body bytes (already have %d/%d)",
00991                           len, bposIn, GWEN_Io_Request_GetBufferSize(rIn));
00992               rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00993                                        GWEN_Io_Request_GetBufferPtr(rIn)+bposIn, len,
00994                                        NULL, NULL,
00995                                        GWEN_Io_Request_GetGuiId(rIn));
00996               GWEN_Io_Request_AddFlags(rOut, GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW);
00997               rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00998               if (rv) {
00999                 GWEN_Io_Request_free(rOut);
01000                 if (rv!=GWEN_ERROR_TRY_AGAIN) {
01001                   xio->lastReadOutResult=rv;
01002                   xio->readRequestIn=NULL;
01003                   DBG_INFO(GWEN_LOGDOMAIN,
01004                            "Aborting in read request (reason: %d)",
01005                            xio->lastReadOutResult);
01006                   GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01007                   GWEN_Io_Request_free(rIn);
01008                   rIn=NULL;
01009                   doneSomething=1;
01010                 }
01011               }
01012               else {
01013                 xio->readRequestOut=rOut;
01014                 doneSomething=1;
01015               }
01016             } /* no bytes to read */
01017             else {
01018               if (xio->currentReadBodySize==0)
01019                 xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
01020               if (xio->currentReadChunkSize==0) {
01021                 xio->currentReadChunkSize=-1;
01022                 xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
01023               }
01024             }
01025           }
01026         } /* if there is no outbound read request */
01027       } /* if inbound request not yet fullfilled */
01028     } /* if not finished */
01029   } /* if there is an inbound read request */
01030 
01031   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01032 }
01033 
01034 
01035 
01036 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest(GWEN_IO_LAYER *io) {
01037   GWEN_IO_LAYER_HTTP *xio;
01038 
01039   assert(io);
01040   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01041   assert(xio);
01042 
01043   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest (%d)", xio->readMode);
01044 
01045   switch(xio->readMode) {
01046   case GWEN_Io_LayerHttp_Mode_Command:
01047   case GWEN_Io_LayerHttp_Mode_Status:
01048   case GWEN_Io_LayerHttp_Mode_Header:
01049   case GWEN_Io_LayerHttp_Mode_ChunkSize:
01050     return GWEN_Io_LayerHttp_WorkOnReadRequest1(io);
01051 
01052   case GWEN_Io_LayerHttp_Mode_Chunk:
01053   case GWEN_Io_LayerHttp_Mode_Body:
01054   case GWEN_Io_LayerHttp_Mode_Finished:
01055   default:
01056     return GWEN_Io_LayerHttp_WorkOnReadRequest2(io);
01057   }
01058 }
01059 
01060 
01061 
01062 /* writing command/status/header */
01063 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest1(GWEN_IO_LAYER *io) {
01064   GWEN_IO_LAYER_HTTP *xio;
01065   int doneSomething=0;
01066 
01067   assert(io);
01068   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01069   assert(xio);
01070 
01071   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest1 (%d)", xio->writeMode);
01072 
01073   if (xio->writeRequestOut) {
01074     if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
01075       GWEN_IO_REQUEST *rOut;
01076       uint32_t bposOut;
01077       uint32_t flagsOut;
01078 
01079       rOut=xio->writeRequestOut;
01080       flagsOut=GWEN_Io_Request_GetFlags(rOut);
01081       bposOut=GWEN_Io_Request_GetBufferPos(rOut);
01082 
01083       DBG_VERBOUS(GWEN_LOGDOMAIN, "Sent %d bytes", bposOut);
01084 
01085       GWEN_Buffer_IncrementPos(xio->writeBuffer, bposOut);
01086       xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(xio->writeRequestOut);
01087 
01088       /* delete outbound request */
01089       GWEN_Io_Request_free(xio->writeRequestOut);
01090       xio->writeRequestOut=NULL;
01091 
01092       doneSomething=1;
01093     }
01094   }
01095 
01096   if (xio->writeRequestIn) {
01097     GWEN_IO_REQUEST *rIn;
01098 
01099     rIn=xio->writeRequestIn;
01100     if (GWEN_Buffer_GetBytesLeft(xio->writeBuffer)) {
01101       if (xio->writeRequestOut==NULL) {
01102         if (xio->lastWriteOutResult) {
01103           xio->writeRequestIn=NULL;
01104           DBG_INFO(GWEN_LOGDOMAIN,
01105                    "Aborting in write request (reason: %d)",
01106                    xio->lastWriteOutResult);
01107           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastWriteOutResult);
01108           GWEN_Io_Request_free(rIn);
01109           rIn=NULL;
01110           doneSomething=1;
01111         }
01112         else {
01113           GWEN_IO_REQUEST *rOut;
01114           int rv;
01115 
01116           DBG_VERBOUS(GWEN_LOGDOMAIN, "Sending %d header bytes", GWEN_Buffer_GetBytesLeft(xio->writeBuffer));
01117           rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
01118                                    (uint8_t*)GWEN_Buffer_GetPosPointer(xio->writeBuffer),
01119                                    GWEN_Buffer_GetBytesLeft(xio->writeBuffer),
01120                                    NULL, NULL,
01121                                    GWEN_Io_Request_GetGuiId(rIn));
01122           GWEN_Io_Request_AddFlags(rOut,
01123                                    GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW |
01124                                    GWEN_IO_REQUEST_FLAGS_FLUSH |
01125                                    GWEN_IO_REQUEST_FLAGS_WRITEALL);
01126           rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
01127           if (rv) {
01128             GWEN_Io_Request_free(rOut);
01129             if (rv!=GWEN_ERROR_TRY_AGAIN) {
01130               xio->lastWriteOutResult=rv;
01131               xio->writeRequestIn=NULL;
01132               DBG_INFO(GWEN_LOGDOMAIN,
01133                        "Aborting in write request (reason: %d)",
01134                        xio->lastWriteOutResult);
01135               GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01136               GWEN_Io_Request_free(rIn);
01137               rIn=NULL;
01138               doneSomething=1;
01139             }
01140           }
01141           else {
01142             xio->writeRequestOut=rOut;
01143             doneSomething=1;
01144           }
01145         } /* if lastOutResult was ok */
01146       } /* if there is no outbound request */
01147     } /* if there still are bytes in the buffer to write */
01148     else {
01149       /* header finished, prepare writing of the body */
01150       GWEN_Buffer_Reset(xio->writeBuffer);
01151       if (xio->currentWriteBodySize!=0)
01152         /* header finished, body follows */
01153         xio->writeMode=GWEN_Io_LayerHttp_Mode_Body;
01154       else
01155         /* no body */
01156         xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01157     }
01158   } /* if there is an inbound request */
01159 
01160 
01161   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01162 }
01163 
01164 
01165 
01166 /* writing body/ finished*/
01167 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest2(GWEN_IO_LAYER *io) {
01168   GWEN_IO_LAYER_HTTP *xio;
01169   int doneSomething=0;
01170 
01171   assert(io);
01172   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01173   assert(xio);
01174 
01175   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest2 (%d)", xio->writeMode);
01176 
01177   if (xio->writeRequestOut) {
01178     if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
01179       GWEN_IO_REQUEST *rOut;
01180 
01181       doneSomething=1;
01182       rOut=xio->writeRequestOut;
01183       if (xio->writeRequestIn) {
01184         uint32_t bposOut;
01185         uint32_t flagsOut;
01186         GWEN_IO_REQUEST *rIn;
01187         uint32_t bposIn;
01188         uint32_t flagsIn;
01189 
01190         rOut=xio->writeRequestOut;
01191         flagsOut=GWEN_Io_Request_GetFlags(rOut);
01192         bposOut=GWEN_Io_Request_GetBufferPos(rOut);
01193 
01194         rIn=xio->writeRequestIn;
01195         flagsIn=GWEN_Io_Request_GetFlags(rIn);
01196         bposIn=GWEN_Io_Request_GetBufferPos(rIn)+bposOut;
01197         GWEN_Io_Request_SetBufferPos(rIn, bposIn);
01198 
01199         DBG_VERBOUS(GWEN_LOGDOMAIN, "Sent %d body bytes (%d)",
01200                     bposOut, GWEN_Io_Request_GetResultCode(rOut));
01201 
01202         /* get last result */
01203         xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(rOut);
01204 
01205         /* delete outbound request */
01206         GWEN_Io_Request_free(xio->writeRequestOut);
01207         xio->writeRequestOut=NULL;
01208 
01209         if (xio->currentWriteBodySize!=-1)
01210           xio->currentWriteBodySize-=bposOut;
01211 
01212         /* check whether the body has been finished */
01213         if (xio->currentWriteBodySize==0) {
01214           /* body finished (in any mode) */
01215           GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
01216           xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01217           if (bposIn<GWEN_Io_Request_GetBufferSize(rIn) &&
01218               (flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL)) {
01219             /* body finished, but caller insists on writing more data, abort */
01220             xio->writeRequestIn=NULL;
01221             DBG_INFO(GWEN_LOGDOMAIN,
01222                      "Aborting in write request (reason: %d)",
01223                      GWEN_ERROR_BAD_SIZE);
01224             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_SIZE);
01225             GWEN_Io_Request_free(rIn);
01226             rIn=NULL;
01227           }
01228         }
01229         else {
01230           /* body not complete (or unknown) */
01231           if (bposIn>=GWEN_Io_Request_GetBufferSize(rIn) ||
01232               (bposIn && !(flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL))) {
01233             /* inbound request fullfilled */
01234             xio->writeRequestIn=NULL;
01235             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
01236             GWEN_Io_Request_free(rIn);
01237             rIn=NULL;
01238           }
01239         }
01240       }
01241     }
01242   }
01243 
01244   if (xio->writeRequestIn) {
01245     GWEN_IO_REQUEST *rIn;
01246 
01247     rIn=xio->writeRequestIn;
01248     if (xio->writeRequestOut==NULL) {
01249       if (xio->lastWriteOutResult) {
01250         xio->writeRequestIn=NULL;
01251         DBG_INFO(GWEN_LOGDOMAIN,
01252                  "Aborting in write request (reason: %d)",
01253                  xio->lastWriteOutResult);
01254         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastWriteOutResult);
01255         GWEN_Io_Request_free(rIn);
01256         rIn=NULL;
01257         doneSomething=1;
01258       }
01259       else {
01260         int len;
01261         int bpos;
01262 
01263         /* create new write request for remaining bytes */
01264         bpos=GWEN_Io_Request_GetBufferPos(rIn);
01265         len=GWEN_Io_Request_GetBufferSize(rIn)-bpos;
01266         if (xio->currentWriteBodySize!=-1 && len>xio->currentWriteBodySize)
01267           /* adapt number of bytes to write */
01268           len=xio->currentWriteBodySize;
01269 
01270         if (len==0) {
01271           if (xio->currentWriteBodySize==0)
01272             GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
01273           xio->writeRequestIn=NULL;
01274           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
01275           GWEN_Io_Request_free(rIn);
01276           rIn=NULL;
01277           doneSomething=1;
01278         }
01279         else {
01280           GWEN_IO_REQUEST *rOut;
01281           int rv;
01282 
01283           /* create new write request for remaining bytes */
01284           DBG_VERBOUS(GWEN_LOGDOMAIN, "Sending %d body bytes", len);
01285           rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
01286                                    GWEN_Io_Request_GetBufferPtr(rIn)+bpos, len,
01287                                    NULL, NULL,
01288                                    GWEN_Io_Request_GetGuiId(rIn));
01289           GWEN_Io_Request_AddFlags(rOut,
01290                                    GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW |
01291                                    GWEN_IO_REQUEST_FLAGS_FLUSH |
01292                                    GWEN_IO_REQUEST_FLAGS_WRITEALL);
01293           rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
01294           if (rv) {
01295             GWEN_Io_Request_free(rOut);
01296             if (rv!=GWEN_ERROR_TRY_AGAIN) {
01297               xio->lastWriteOutResult=rv;
01298               xio->writeRequestIn=NULL;
01299               DBG_INFO(GWEN_LOGDOMAIN,
01300                        "Aborting in write request (reason: %d)",
01301                        xio->lastWriteOutResult);
01302               GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01303               GWEN_Io_Request_free(rIn);
01304               rIn=NULL;
01305               doneSomething=1;
01306             }
01307           }
01308           else {
01309             xio->writeRequestOut=rOut;
01310             doneSomething=1;
01311           }
01312         }
01313       } /* if lastOutResult was ok */
01314     }
01315 
01316 
01317   } /* if there is an inbound request */
01318 
01319 
01320   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01321 }
01322 
01323 
01324 
01325 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest(GWEN_IO_LAYER *io) {
01326   GWEN_IO_LAYER_HTTP *xio;
01327 
01328   assert(io);
01329   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01330   assert(xio);
01331 
01332   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest (%d)", xio->writeMode);
01333 
01334   switch(xio->writeMode) {
01335   case GWEN_Io_LayerHttp_Mode_Command:
01336   case GWEN_Io_LayerHttp_Mode_Status:
01337   case GWEN_Io_LayerHttp_Mode_Header:
01338   case GWEN_Io_LayerHttp_Mode_ChunkSize:
01339     return GWEN_Io_LayerHttp_WorkOnWriteRequest1(io);
01340 
01341   case GWEN_Io_LayerHttp_Mode_Chunk:
01342   case GWEN_Io_LayerHttp_Mode_Body:
01343   case GWEN_Io_LayerHttp_Mode_Finished:
01344   default:
01345     return GWEN_Io_LayerHttp_WorkOnWriteRequest2(io);
01346   }
01347 }
01348 
01349 
01350 
01351 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnRequests(GWEN_IO_LAYER *io) {
01352   GWEN_IO_LAYER_HTTP *xio;
01353   int doneSomething=0;
01354 
01355   assert(io);
01356   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01357   assert(xio);
01358 
01359   /* work on read request */
01360   if (GWEN_Io_LayerHttp_WorkOnReadRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01361     doneSomething=1;
01362 
01363   /* work on write request */
01364   if (GWEN_Io_LayerHttp_WorkOnWriteRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01365     doneSomething=1;
01366 
01367   /* let base layer work */
01368   if (GWEN_Io_Layer_WorkOnRequests(GWEN_Io_Layer_GetBaseLayer(io))!=GWEN_Io_Layer_WorkResultBlocking)
01369     doneSomething=1;
01370 
01371   if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
01372     GWEN_IO_LAYER *newIo;
01373 
01374     newIo=GWEN_Io_Layer_GetNextIncomingLayer(GWEN_Io_Layer_GetBaseLayer(io));
01375     if (newIo) {
01376       GWEN_IO_LAYER *newNewIo;
01377       GWEN_DB_NODE *dbSrc;
01378       GWEN_DB_NODE *dbDst;
01379       uint32_t fl;
01380 
01381       fl=GWEN_Io_Layer_GetFlags(io);
01382       newNewIo=GWEN_Io_LayerHttp_new(newIo);
01383       GWEN_Io_Layer_AddFlags(newNewIo, GWEN_IO_LAYER_FLAGS_PASSIVE);
01384       GWEN_Io_Layer_AddFlags(newNewIo, fl & 0xffff);
01385       /* copy command */
01386       dbDst=GWEN_Io_LayerHttp_GetDbCommandOut(newNewIo);
01387       dbSrc=xio->dbCommandOut;
01388       GWEN_DB_AddGroupChildren(dbDst, dbSrc);
01389 
01390       GWEN_Io_Layer_AddIncomingLayer(io, newNewIo);
01391       doneSomething=1;
01392     }
01393   }
01394 
01395   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01396 }
01397 
01398 
01399 
01400 
01401 int GWEN_Io_LayerHttp_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01402   GWEN_IO_LAYER_HTTP *xio;
01403   GWEN_IO_LAYER_STATUS st;
01404   uint32_t lflags;
01405   uint32_t rflags;
01406 
01407   assert(io);
01408   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01409   assert(xio);
01410 
01411   st=GWEN_Io_Layer_GetStatus(io);
01412   lflags=GWEN_Io_Layer_GetFlags(io);
01413   rflags=GWEN_Io_Request_GetFlags(r);
01414 
01415   switch(GWEN_Io_Request_GetType(r)) {
01416   case GWEN_Io_Request_TypeRead:
01417     /* check status */
01418     if (st!=GWEN_Io_Layer_StatusConnected) {
01419       DBG_INFO(GWEN_LOGDOMAIN, "Layer not connected (%d)", st);
01420       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01421       return GWEN_ERROR_NOT_OPEN;
01422     }
01423 
01424     if (xio->lastReadOutResult) {
01425       DBG_INFO(GWEN_LOGDOMAIN, "Unable to read (%d)", xio->lastReadOutResult);
01426       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
01427       return xio->lastReadOutResult;
01428     }
01429 
01430     /* check whether we already have a read request */
01431     if (xio->readRequestIn) {
01432       DBG_INFO(GWEN_LOGDOMAIN, "There already is a read request");
01433       return GWEN_ERROR_TRY_AGAIN;
01434     }
01435 
01436     if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETBEGIN) {
01437       if (xio->readMode!=GWEN_Io_LayerHttp_Mode_Idle) {
01438         DBG_INFO(GWEN_LOGDOMAIN, "Packetbegin requested while there is still a packet in work");
01439         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01440         return GWEN_ERROR_INVALID;
01441       }
01442 
01443       GWEN_Buffer_Reset(xio->readBuffer);
01444       GWEN_DB_ClearGroup(xio->dbCommandIn, NULL);
01445       GWEN_DB_ClearGroup(xio->dbStatusIn, NULL);
01446       GWEN_DB_ClearGroup(xio->dbHeaderIn, NULL);
01447       xio->currentReadChunkSize=-1;
01448       xio->currentReadBodySize=-1;
01449       xio->readLineFinished=0;
01450       if ((lflags & GWEN_IO_LAYER_HTTP_FLAGS_IPC) ||
01451           (lflags & GWEN_IO_LAYER_FLAGS_PASSIVE))
01452         xio->readMode=GWEN_Io_LayerHttp_Mode_Command;
01453       else
01454         xio->readMode=GWEN_Io_LayerHttp_Mode_Status;
01455     }
01456     else {
01457       if (xio->readMode!=GWEN_Io_LayerHttp_Mode_ChunkSize &&
01458           xio->readMode!=GWEN_Io_LayerHttp_Mode_Chunk &&
01459           xio->readMode!=GWEN_Io_LayerHttp_Mode_Body) {
01460         DBG_INFO(GWEN_LOGDOMAIN, "Bad read mode and flag GWEN_IO_REQUEST_FLAGS_PACKETBEGIN not set");
01461         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01462         return GWEN_ERROR_INVALID;
01463       }
01464     }
01465 
01466     /* enqueue request */
01467     xio->readRequestIn=r;
01468     GWEN_Io_Request_Attach(xio->readRequestIn);
01469     break;
01470 
01471   case GWEN_Io_Request_TypeWrite:
01472     /* check status */
01473     if (st!=GWEN_Io_Layer_StatusConnected) {
01474       DBG_INFO(GWEN_LOGDOMAIN, "Layer is not connected");
01475       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01476       return GWEN_ERROR_NOT_OPEN;
01477     }
01478 
01479     /* check whether we already have a read request */
01480     if (xio->writeRequestIn) {
01481       DBG_INFO(GWEN_LOGDOMAIN, "There already is a write request");
01482       return GWEN_ERROR_TRY_AGAIN;
01483     }
01484 
01485     if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETBEGIN) {
01486       int rv;
01487 
01488       if (xio->writeMode!=GWEN_Io_LayerHttp_Mode_Idle && xio->writeMode!=GWEN_Io_LayerHttp_Mode_Finished) {
01489         DBG_INFO(GWEN_LOGDOMAIN, "Packetbegin requested while there is still a packet in work");
01490         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01491         return GWEN_ERROR_INVALID;
01492       }
01493 
01494       DBG_VERBOUS(GWEN_LOGDOMAIN, "Packet begin");
01495       GWEN_Buffer_Reset(xio->writeBuffer);
01496       /* Write command/status */
01497       if ((lflags & GWEN_IO_LAYER_HTTP_FLAGS_IPC) ||
01498           !(lflags & GWEN_IO_LAYER_FLAGS_PASSIVE)) {
01499         rv=GWEN_Io_LayerHttp_WriteCommand(io, xio->writeBuffer);
01500         xio->writeMode=GWEN_Io_LayerHttp_Mode_Command;
01501       }
01502       else {
01503         rv=GWEN_Io_LayerHttp_WriteStatus(io, xio->writeBuffer);
01504         xio->writeMode=GWEN_Io_LayerHttp_Mode_Status;
01505       }
01506       if (rv<0) {
01507         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01508         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
01509         xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01510         return rv;
01511       }
01512 
01513       if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETEND)
01514         /* both flags packet begin and end are given, so we already know the content-length */
01515         GWEN_DB_SetIntValue(xio->dbHeaderOut, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-length",
01516                             GWEN_Io_Request_GetBufferSize(r));
01517 
01518       /* write header into buffer, get body size */
01519       rv=GWEN_Io_LayerHttp_WriteHeader(io, xio->writeBuffer);
01520       if (rv<0) {
01521         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01522         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
01523         xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01524         return rv;
01525       }
01526       GWEN_Buffer_Rewind(xio->writeBuffer);
01527       xio->writeMode=GWEN_Io_LayerHttp_Mode_Header;
01528       DBG_VERBOUS(GWEN_LOGDOMAIN, "Buffer: %d/%d",
01529                   GWEN_Buffer_GetBytesLeft(xio->writeBuffer),
01530                   GWEN_Buffer_GetUsedBytes(xio->writeBuffer));
01531     }
01532     else {
01533       if (xio->writeMode!=GWEN_Io_LayerHttp_Mode_Body) {
01534         if ((GWEN_Io_Request_GetBufferSize(r)==0) &&
01535             (rflags & GWEN_IO_REQUEST_FLAGS_FLUSH)) {
01536           /* this is just a flush request */
01537           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01538           return 0;
01539         }
01540         else {
01541           DBG_INFO(GWEN_LOGDOMAIN, "Bad write mode and flag GWEN_IO_REQUEST_FLAGS_PACKETBEGIN not set");
01542           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01543           return GWEN_ERROR_INVALID;
01544         }
01545       }
01546     }
01547 
01548     /* enqueue request */
01549     xio->writeRequestIn=r;
01550     GWEN_Io_Request_Attach(xio->writeRequestIn);
01551     break;
01552 
01553   case GWEN_Io_Request_TypeConnect:
01554     /* check status */
01555     if (st!=GWEN_Io_Layer_StatusUnconnected &&
01556         st!=GWEN_Io_Layer_StatusDisconnected) {
01557       DBG_INFO(GWEN_LOGDOMAIN, "Layer not un-/disconnected");
01558       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01559       return GWEN_ERROR_NOT_OPEN;
01560     }
01561     else {
01562       /* reset all structures */
01563       xio->lastReadOutResult=0;
01564       GWEN_Buffer_Reset(xio->readBuffer);
01565       xio->readMode=GWEN_Io_LayerHttp_Mode_Idle;
01566       xio->currentReadChunkSize=-1;
01567       xio->currentReadBodySize=-1;
01568       xio->readLineFinished=0;
01569 
01570       xio->lastWriteOutResult=0;
01571       GWEN_Buffer_Reset(xio->writeBuffer);
01572       xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01573 
01574       GWEN_DB_ClearGroup(xio->dbCommandIn, NULL);
01575       GWEN_DB_ClearGroup(xio->dbStatusIn, NULL);
01576       GWEN_DB_ClearGroup(xio->dbHeaderIn, NULL);
01577 
01578       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
01579       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01580       DBG_INFO(GWEN_LOGDOMAIN, "Layer now connected");
01581     }
01582     break;
01583 
01584   case GWEN_Io_Request_TypeDisconnect:
01585     /* check status */
01586     if (st!=GWEN_Io_Layer_StatusConnected) {
01587       DBG_INFO(GWEN_LOGDOMAIN, "IO layer is not open");
01588       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01589       return GWEN_ERROR_NOT_OPEN;
01590     }
01591     else {
01592       /* abort incoming requests, if any */
01593       GWEN_Io_LayerHttp_AbortInRequests(io, GWEN_ERROR_ABORTED);
01594       GWEN_Io_LayerHttp_AbortOutRequests(io);
01595 
01596       /* closed */
01597       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01598       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01599     }
01600     break;
01601 
01602   default:
01603     DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
01604     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
01605     return GWEN_ERROR_NOT_SUPPORTED;
01606   }
01607 
01608   return 0;
01609 }
01610 
01611 
01612 
01613 int GWEN_Io_LayerHttp_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01614   GWEN_IO_LAYER_HTTP *xio;
01615 
01616   assert(io);
01617   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01618   assert(xio);
01619 
01620   switch(GWEN_Io_Request_GetType(r)) {
01621   case GWEN_Io_Request_TypeRead:
01622     if (xio->readRequestIn==r) {
01623       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted read request");
01624       xio->readRequestIn=NULL;
01625       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01626       GWEN_Io_Request_free(r);
01627     }
01628     else {
01629       /* not my request */
01630       DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
01631       return GWEN_ERROR_INVALID;
01632     }
01633     break;
01634 
01635   case GWEN_Io_Request_TypeWrite:
01636     if (xio->writeRequestIn==r) {
01637       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted write request");
01638       xio->writeRequestIn=NULL;
01639       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01640       GWEN_Io_Request_free(r);
01641     }
01642     else {
01643       /* not my request */
01644       DBG_INFO(GWEN_LOGDOMAIN, "Write request not registered with this io layer");
01645       return GWEN_ERROR_INVALID;
01646     }
01647     break;
01648 
01649   default:
01650     break;
01651   }
01652 
01653   return 0;
01654 }
01655 
01656 
01657 
01658 int GWEN_Io_LayerHttp_HasWaitingRequests(GWEN_IO_LAYER *io) {
01659   GWEN_IO_LAYER_HTTP *xio;
01660 
01661   assert(io);
01662   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01663   assert(xio);
01664 
01665   if (xio->readRequestIn || xio->writeRequestIn)
01666     return 1;
01667   else
01668     return 0;
01669 }
01670 
01671 
01672 
01673 
01674 
01675 

Generated on Wed Sep 3 15:21:58 2008 for gwenhywfar by  doxygen 1.5.6