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 header */
00411     xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00412   }
00413 
00414   return 0;
00415 }
00416 
00417 
00418 
00419 int GWEN_Io_LayerHttp_WriteCommand(GWEN_IO_LAYER *io, GWEN_BUFFER *buf) {
00420   GWEN_IO_LAYER_HTTP *xio;
00421   const char *s;
00422 
00423   assert(io);
00424   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00425   assert(xio);
00426 
00427   s=GWEN_DB_GetCharValue(xio->dbCommandOut, "command", 0, "GET");
00428   GWEN_Buffer_AppendString(buf, s);
00429   GWEN_Buffer_AppendString(buf, " ");
00430 
00431   s=GWEN_DB_GetCharValue(xio->dbCommandOut, "url", 0, "/");
00432   GWEN_Buffer_AppendString(buf, s);
00433   GWEN_Buffer_AppendString(buf, " ");
00434 
00435   s=GWEN_DB_GetCharValue(xio->dbCommandOut, "protocol", 0, "HTTP/1.0");
00436   GWEN_Buffer_AppendString(buf, s);
00437   GWEN_Buffer_AppendString(buf, "\r\n");
00438 
00439   return 0;
00440 }
00441 
00442 
00443 
00444 int GWEN_Io_LayerHttp_WriteStatus(GWEN_IO_LAYER *io, GWEN_BUFFER *buf) {
00445   GWEN_IO_LAYER_HTTP *xio;
00446   const char *s;
00447   int i;
00448   char numbuf[32];
00449 
00450   assert(io);
00451   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00452   assert(xio);
00453 
00454   s=GWEN_DB_GetCharValue(xio->dbStatusOut, "protocol", 0, "HTTP/1.0");
00455   GWEN_Buffer_AppendString(buf, s);
00456   GWEN_Buffer_AppendString(buf, " ");
00457 
00458   i=GWEN_DB_GetIntValue(xio->dbStatusOut, "code", 0, -1);
00459   if (i==-1) {
00460     DBG_INFO(GWEN_LOGDOMAIN, "Missing status code");
00461     return GWEN_ERROR_NO_DATA;
00462   }
00463   snprintf(numbuf, sizeof(numbuf), "%d ", i);
00464   GWEN_Buffer_AppendString(buf, numbuf);
00465 
00466   s=GWEN_DB_GetCharValue(xio->dbStatusOut, "text", 0, "No text.");
00467   GWEN_Buffer_AppendString(buf, s);
00468   GWEN_Buffer_AppendString(buf, "\r\n");
00469 
00470   return 0;
00471 }
00472 
00473 
00474 
00475 int GWEN_Io_LayerHttp_WriteHeader(GWEN_IO_LAYER *io, GWEN_BUFFER *buf) {
00476   GWEN_IO_LAYER_HTTP *xio;
00477   int i;
00478   GWEN_DB_NODE *dbVar;
00479 
00480   assert(io);
00481   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00482   assert(xio);
00483 
00484   i=GWEN_DB_GetIntValue(xio->dbHeaderOut, "Content-Length", 0, -1);
00485   if (i!=-1)
00486     xio->currentWriteBodySize=i;
00487 
00488   dbVar=GWEN_DB_GetFirstVar(xio->dbHeaderOut);
00489   while (dbVar) {
00490     GWEN_DB_NODE *dbVal;
00491 
00492     /* only handle first value */
00493     dbVal=GWEN_DB_GetFirstValue(dbVar);
00494     if (dbVal) {
00495       GWEN_DB_NODE_TYPE vtype;
00496 
00497       vtype=GWEN_DB_GetValueType(dbVal);
00498       if (vtype==GWEN_DB_NodeType_ValueChar) {
00499         const char *s;
00500 
00501         GWEN_Buffer_AppendString(buf, GWEN_DB_VariableName(dbVar));
00502         GWEN_Buffer_AppendString(buf, ":");
00503         s=GWEN_DB_GetCharValueFromNode(dbVal);
00504         if (s)
00505           GWEN_Buffer_AppendString(buf, s);
00506         GWEN_Buffer_AppendString(buf, "\r\n");
00507       }
00508       else if (vtype==GWEN_DB_NodeType_ValueInt) {
00509         i=GWEN_DB_GetIntValueFromNode(dbVal);
00510         if (i!=-1 || strcasecmp(GWEN_DB_VariableName(dbVar), "Content-Length")==0) {
00511           char numbuf[32];
00512 
00513           /* dont write body size of -1 */
00514           GWEN_Buffer_AppendString(buf, GWEN_DB_VariableName(dbVar));
00515           GWEN_Buffer_AppendString(buf, ":");
00516           snprintf(numbuf, sizeof(numbuf), "%d", i);
00517           GWEN_Buffer_AppendString(buf, numbuf);
00518           GWEN_Buffer_AppendString(buf, "\r\n");
00519         }
00520       }
00521       else {
00522         DBG_INFO(GWEN_LOGDOMAIN, "Variable type %d of var [%s] not supported",
00523                  vtype, GWEN_DB_VariableName(dbVar));
00524         return GWEN_ERROR_BAD_DATA;
00525       }
00526     }
00527     dbVar=GWEN_DB_GetNextVar(dbVar);
00528   }
00529 
00530   /* finalize header */
00531   GWEN_Buffer_AppendString(buf, "\r\n");
00532 
00533   return 0;
00534 }
00535 
00536 
00537 
00538 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest1(GWEN_IO_LAYER *io) {
00539   GWEN_IO_LAYER_HTTP *xio;
00540   int doneSomething=0;
00541 
00542   assert(io);
00543   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00544   assert(xio);
00545 
00546   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest1 (%d)", xio->readMode);
00547 
00548   if (xio->readRequestOut) {
00549     /* check for finished outbound read request */
00550     if (GWEN_Io_Request_GetStatus(xio->readRequestOut)==GWEN_Io_Request_StatusFinished) {
00551       uint32_t bpos;
00552       uint32_t flags;
00553 
00554       doneSomething=1;
00555 
00556       /* get all available data */
00557       xio->lastReadOutResult=GWEN_Io_Request_GetResultCode(xio->readRequestOut);
00558       flags=GWEN_Io_Request_GetFlags(xio->readRequestOut);
00559       bpos=GWEN_Io_Request_GetBufferPos(xio->readRequestOut);
00560 
00561       /* adjusting buffer pointers */
00562       GWEN_Buffer_IncrementPos(xio->readBuffer, bpos);
00563       GWEN_Buffer_AdjustUsedBytes(xio->readBuffer);
00564 
00565       if (flags & GWEN_IO_REQUEST_FLAGS_PACKETEND) {
00566         xio->readLineFinished=1;
00567       }
00568 
00569       DBG_VERBOUS(GWEN_LOGDOMAIN, "Received %d bytes (%s)",
00570                   bpos, (xio->readLineFinished)?"line finished":"line open");
00571 
00572       /* request handled */
00573       GWEN_Io_Request_free(xio->readRequestOut);
00574       xio->readRequestOut=NULL;
00575     }
00576   } /* if readRequestOut */
00577 
00578   if (xio->readRequestIn) {
00579     GWEN_IO_REQUEST *rIn;
00580 
00581     rIn=xio->readRequestIn;
00582     if (xio->readLineFinished==0) {
00583       if (xio->readRequestOut==NULL) {
00584         int rv;
00585 
00586         if (xio->lastReadOutResult) {
00587           xio->readRequestIn=NULL;
00588           DBG_INFO(GWEN_LOGDOMAIN, "Aborting out read request (reason: %d)",
00589                    xio->lastReadOutResult);
00590           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00591           GWEN_Io_Request_free(rIn);
00592           rIn=NULL;
00593           doneSomething=1;
00594         }
00595         else {
00596           rv=GWEN_Buffer_AllocRoom(xio->readBuffer, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00597           if (rv<0) {
00598             xio->readRequestIn=NULL;
00599             xio->lastReadOutResult=GWEN_ERROR_MEMORY_FULL;
00600             DBG_INFO(GWEN_LOGDOMAIN, "Aborting out read request (reason: %d)",
00601                      xio->lastReadOutResult);
00602             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_MEMORY_FULL);
00603             GWEN_Io_Request_free(rIn);
00604             rIn=NULL;
00605             doneSomething=1;
00606           }
00607           else {
00608             GWEN_IO_REQUEST *rOut;
00609 
00610             DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d header bytes", GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00611             rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00612                                      (uint8_t*)GWEN_Buffer_GetPosPointer(xio->readBuffer),
00613                                      GWEN_IO_LAYER_HTTP_LINE_STEPSIZE,
00614                                      NULL, NULL,
00615                                      GWEN_Io_Request_GetGuiId(rIn));
00616             rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00617             if (rv) {
00618               if (rv!=GWEN_ERROR_TRY_AGAIN) {
00619                 GWEN_Io_Request_free(rOut);
00620                 xio->readRequestIn=NULL;
00621                 xio->lastReadOutResult=rv;
00622                 DBG_INFO(GWEN_LOGDOMAIN,
00623                          "Aborting out read request (reason: %d)",
00624                          xio->lastReadOutResult);
00625                 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00626                 GWEN_Io_Request_free(rIn);
00627                 rIn=NULL;
00628                 doneSomething=1;
00629               }
00630             }
00631             else {
00632               DBG_INFO(GWEN_LOGDOMAIN, "Added header read request");
00633               xio->readRequestOut=rOut;
00634               doneSomething=1;
00635             }
00636           } /* if allocRoom succeeded */
00637         } /* if last result was ok */
00638       } /* if no readRequestOut */
00639     } /* if line not finished */
00640     else {
00641       int rv;
00642 
00643       /* line finished */
00644       doneSomething=1;
00645       xio->readLineFinished=0; /* reset for next line */
00646       switch(xio->readMode) {
00647       case GWEN_Io_LayerHttp_Mode_Command:
00648         DBG_DEBUG(GWEN_LOGDOMAIN, "Command received: [%s]", GWEN_Buffer_GetStart(xio->readBuffer));
00649         rv=GWEN_Io_LayerHttp_ParseCommand(io, GWEN_Buffer_GetStart(xio->readBuffer));
00650         if (rv) {
00651           xio->lastReadOutResult=rv;
00652           xio->readRequestIn=NULL;
00653           DBG_INFO(GWEN_LOGDOMAIN,
00654                    "Aborting in read request (reason: %d)",
00655                    xio->lastReadOutResult);
00656           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00657           GWEN_Io_Request_free(rIn);
00658           rIn=NULL;
00659         }
00660         else {
00661           xio->lastHeaderPos=0;
00662           xio->readMode=GWEN_Io_LayerHttp_Mode_Header;
00663         }
00664         GWEN_Buffer_Reset(xio->readBuffer);
00665         break;
00666 
00667       case GWEN_Io_LayerHttp_Mode_Status:
00668         DBG_DEBUG(GWEN_LOGDOMAIN, "Status received: [%s]", GWEN_Buffer_GetStart(xio->readBuffer));
00669         rv=GWEN_Io_LayerHttp_ParseStatus(io, GWEN_Buffer_GetStart(xio->readBuffer));
00670         if (rv) {
00671           xio->lastReadOutResult=rv;
00672           xio->readRequestIn=NULL;
00673           DBG_INFO(GWEN_LOGDOMAIN,
00674                    "Aborting in read request (reason: %d)",
00675                    xio->lastReadOutResult);
00676           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00677           GWEN_Io_Request_free(rIn);
00678           rIn=NULL;
00679         }
00680         else {
00681           xio->lastHeaderPos=0;
00682           xio->readMode=GWEN_Io_LayerHttp_Mode_Header;
00683         }
00684         GWEN_Buffer_Reset(xio->readBuffer);
00685         break;
00686 
00687       case GWEN_Io_LayerHttp_Mode_Header: {
00688         uint32_t i;
00689 
00690         DBG_DEBUG(GWEN_LOGDOMAIN, "Header received: [%s]",
00691                   GWEN_Buffer_GetStart(xio->readBuffer)+xio->lastHeaderPos);
00692         i=GWEN_Buffer_GetUsedBytes(xio->readBuffer);
00693         /* append line feed for header to allow parsing of the different lines */
00694         GWEN_Buffer_AppendByte(xio->readBuffer, 10);
00695         if ((i-xio->lastHeaderPos)==0) {
00696           /* header finished, parse it. NOTE: This function will also determine the next
00697            * readMode and the size of the body (if any) */
00698           rv=GWEN_Io_LayerHttp_ParseHeader(io, GWEN_Buffer_GetStart(xio->readBuffer));
00699           if (rv<0) {
00700             xio->lastReadOutResult=rv;
00701             xio->readRequestIn=NULL;
00702             DBG_INFO(GWEN_LOGDOMAIN,
00703                      "Aborting in read request (reason: %d)",
00704                      xio->lastReadOutResult);
00705             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00706             GWEN_Io_Request_free(rIn);
00707             rIn=NULL;
00708           }
00709           GWEN_Buffer_Reset(xio->readBuffer);
00710         }
00711         else {
00712           xio->lastHeaderPos=i+1; /* count the added #10 */
00713           if (xio->readRequestOut==NULL) {
00714             int rv;
00715 
00716             if (xio->lastReadOutResult) {
00717               xio->readRequestIn=NULL;
00718               DBG_INFO(GWEN_LOGDOMAIN,
00719                        "Aborting in read request (reason: %d)",
00720                        xio->lastReadOutResult);
00721               GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00722               GWEN_Io_Request_free(rIn);
00723               rIn=NULL;
00724               doneSomething=1;
00725             }
00726             else {
00727               /* read the next header line */
00728               rv=GWEN_Buffer_AllocRoom(xio->readBuffer, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00729               if (rv<0) {
00730                 xio->readRequestIn=NULL;
00731                 xio->lastReadOutResult=GWEN_ERROR_MEMORY_FULL;
00732                 DBG_INFO(GWEN_LOGDOMAIN,
00733                          "Aborting in read request (reason: %d)",
00734                          xio->lastReadOutResult);
00735                 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_MEMORY_FULL);
00736                 GWEN_Io_Request_free(rIn);
00737                 rIn=NULL;
00738                 doneSomething=1;
00739               }
00740               else {
00741                 GWEN_IO_REQUEST *rOut;
00742 
00743                 DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d header bytes", GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00744                 rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00745                                          (uint8_t*)GWEN_Buffer_GetPosPointer(xio->readBuffer),
00746                                          GWEN_IO_LAYER_HTTP_LINE_STEPSIZE,
00747                                          NULL, NULL,
00748                                          GWEN_Io_Request_GetGuiId(rIn));
00749                 rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00750                 if (rv) {
00751                   if (rv!=GWEN_ERROR_TRY_AGAIN) {
00752                     GWEN_Io_Request_free(rOut);
00753                     xio->readRequestIn=NULL;
00754                     xio->lastReadOutResult=rv;
00755                     DBG_INFO(GWEN_LOGDOMAIN,
00756                              "Aborting in read request (reason: %d)",
00757                              xio->lastReadOutResult);
00758                     GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00759                     GWEN_Io_Request_free(rIn);
00760                     rIn=NULL;
00761                     doneSomething=1;
00762                   }
00763                 }
00764                 else {
00765                   DBG_INFO(GWEN_LOGDOMAIN, "Added header read request");
00766                   xio->readRequestOut=rOut;
00767                   doneSomething=1;
00768                 }
00769               } /* if allocRoom succeeded */
00770             }
00771           } /* if no readRequestOut */
00772         }
00773         break;
00774       }
00775 
00776       case GWEN_Io_LayerHttp_Mode_ChunkSize: {
00777         int csize;
00778 
00779         if (1!=sscanf(GWEN_Buffer_GetStart(xio->readBuffer), "%d", &csize)) {
00780           DBG_INFO(GWEN_LOGDOMAIN, "Invalid chunksize [%s]", GWEN_Buffer_GetStart(xio->readBuffer));
00781           xio->lastReadOutResult=GWEN_ERROR_BAD_DATA;
00782           xio->readRequestIn=NULL;
00783           DBG_INFO(GWEN_LOGDOMAIN,
00784                    "Aborting in read request (reason: %d)",
00785                    xio->lastReadOutResult);
00786           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_DATA);
00787           GWEN_Io_Request_free(rIn);
00788           rIn=NULL;
00789         }
00790         else {
00791           xio->currentReadChunkSize=csize;
00792           if (csize==0) {
00793             DBG_INFO(GWEN_LOGDOMAIN, "Last chunk received");
00794             xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00795             GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00796           }
00797           else {
00798             DBG_INFO(GWEN_LOGDOMAIN, "Started reading next chunk");
00799             xio->readMode=GWEN_Io_LayerHttp_Mode_Chunk;
00800           }
00801         }
00802         break;
00803       }
00804 
00805       default:
00806         /* should never reach this point */
00807         assert(0);
00808         break;
00809       }
00810     } /* if line finished */
00811   } /* if readRequestIn */
00812 
00813   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00814 }
00815 
00816 
00817 
00818 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest2(GWEN_IO_LAYER *io) {
00819   GWEN_IO_LAYER_HTTP *xio;
00820   int doneSomething=0;
00821 
00822   assert(io);
00823   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00824   assert(xio);
00825 
00826   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest2 (%d)", xio->readMode);
00827 
00828   if (xio->readRequestOut) {
00829     /* check for finished outbound read request */
00830     if (GWEN_Io_Request_GetStatus(xio->readRequestOut)==GWEN_Io_Request_StatusFinished) {
00831       GWEN_IO_REQUEST *rOut;
00832       uint32_t bposOut;
00833       uint32_t flagsOut;
00834 
00835       rOut=xio->readRequestOut;
00836       flagsOut=GWEN_Io_Request_GetFlags(rOut);
00837       bposOut=GWEN_Io_Request_GetBufferPos(rOut);
00838 
00839       doneSomething=1;
00840 
00841       if (xio->readRequestIn) {
00842         GWEN_IO_REQUEST *rIn;
00843         uint32_t bposIn;
00844         uint32_t flagsIn;
00845 
00846         rIn=xio->readRequestIn;
00847         flagsIn=GWEN_Io_Request_GetFlags(rIn);
00848         bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00849 
00850         DBG_VERBOUS(GWEN_LOGDOMAIN, "Received %d (total: %d) bytes", bposIn, bposIn+bposOut);
00851 
00852         /* get all available data */
00853         xio->lastReadOutResult=GWEN_Io_Request_GetResultCode(xio->readRequestOut);
00854 
00855         /* delete outbound request */
00856         GWEN_Io_Request_free(xio->readRequestOut);
00857         xio->readRequestOut=NULL;
00858 
00859         /* advance point in incoming buffer by amount of data read */
00860         bposIn+=bposOut;
00861         GWEN_Io_Request_SetBufferPos(rIn, bposIn);
00862         /* decrease number of bytes to read for body */
00863         if (xio->currentReadBodySize!=-1) {
00864           xio->currentReadBodySize-=bposOut;
00865         }
00866         /* decrease number of bytes to read for chunk (if any) */
00867         if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk) {
00868           xio->currentReadChunkSize-=bposOut;
00869         }
00870         /* check whether the body has been finished */
00871         if (xio->currentReadBodySize==0) {
00872           /* body finished (in any mode) */
00873           GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00874           xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00875         }
00876         else {
00877           if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk && xio->currentReadChunkSize==0) {
00878             /* chunk finished, next step is to read the size of the next chunk */
00879             xio->currentReadChunkSize=-1;
00880             xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
00881           }
00882         }
00883       }
00884     }
00885   }
00886 
00887   if (xio->readRequestIn) {
00888     GWEN_IO_REQUEST *rIn;
00889     uint32_t flagsIn;
00890 
00891     rIn=xio->readRequestIn;
00892     flagsIn=GWEN_Io_Request_GetFlags(rIn);
00893 
00894     if (xio->readMode==GWEN_Io_LayerHttp_Mode_Finished) {
00895       uint32_t bposIn;
00896 
00897       GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00898       bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00899       if (bposIn<GWEN_Io_Request_GetBufferSize(rIn) &&
00900           (flagsIn & GWEN_IO_REQUEST_FLAGS_READALL)) {
00901         /* fixed size has been given but can't be fulfilled, so return an error here */
00902         xio->readRequestIn=NULL;
00903         DBG_INFO(GWEN_LOGDOMAIN,
00904                  "Aborting in read request (reason: %d)",
00905                  GWEN_ERROR_BAD_SIZE);
00906         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_SIZE);
00907         GWEN_Io_Request_free(rIn);
00908         rIn=NULL;
00909       }
00910       else {
00911         /* request finished */
00912         xio->readRequestIn=NULL;
00913         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
00914         GWEN_Io_Request_free(rIn);
00915         rIn=NULL;
00916       }
00917       xio->readMode=GWEN_Io_LayerHttp_Mode_Idle;
00918       doneSomething=1;
00919     } /* if finished */
00920     else {
00921       uint32_t len;
00922       uint32_t bposIn;
00923 
00924       bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00925       len=GWEN_Io_Request_GetBufferSize(rIn)-bposIn;
00926       if (len==0) {
00927         /* inbound read request fullfilled */
00928         xio->readRequestIn=NULL;
00929         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
00930         GWEN_Io_Request_free(rIn);
00931         rIn=NULL;
00932         doneSomething=1;
00933       } /* if request fullfilled */
00934       else {
00935         if (xio->readRequestOut==NULL) {
00936           if (xio->lastReadOutResult) {
00937             xio->readRequestIn=NULL;
00938             DBG_INFO(GWEN_LOGDOMAIN,
00939                      "Aborting in read request (reason: %d)",
00940                      xio->lastReadOutResult);
00941             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00942             GWEN_Io_Request_free(rIn);
00943             rIn=NULL;
00944             doneSomething=1;
00945           }
00946           else {
00947             if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk &&
00948                 xio->currentReadChunkSize!=-1 &&
00949                 len>xio->currentReadChunkSize)
00950               len=xio->currentReadChunkSize;
00951             else if (xio->readMode==GWEN_Io_LayerHttp_Mode_Body &&
00952                      xio->currentReadBodySize!=-1 &&
00953                      len>xio->currentReadBodySize)
00954               len=xio->currentReadBodySize;
00955 
00956             if (len) {
00957               GWEN_IO_REQUEST *rOut;
00958               int rv;
00959 
00960               DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d body bytes (already have %d/%d)",
00961                           len, bposIn, GWEN_Io_Request_GetBufferSize(rIn));
00962               rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00963                                        GWEN_Io_Request_GetBufferPtr(rIn)+bposIn, len,
00964                                        NULL, NULL,
00965                                        GWEN_Io_Request_GetGuiId(rIn));
00966               GWEN_Io_Request_AddFlags(rOut, GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW);
00967               rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00968               if (rv) {
00969                 GWEN_Io_Request_free(rOut);
00970                 if (rv!=GWEN_ERROR_TRY_AGAIN) {
00971                   xio->lastReadOutResult=rv;
00972                   xio->readRequestIn=NULL;
00973                   DBG_INFO(GWEN_LOGDOMAIN,
00974                            "Aborting in read request (reason: %d)",
00975                            xio->lastReadOutResult);
00976                   GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00977                   GWEN_Io_Request_free(rIn);
00978                   rIn=NULL;
00979                   doneSomething=1;
00980                 }
00981               }
00982               else {
00983                 xio->readRequestOut=rOut;
00984                 doneSomething=1;
00985               }
00986             } /* no bytes to read */
00987             else {
00988               if (xio->currentReadBodySize==0)
00989                 xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00990               if (xio->currentReadChunkSize==0) {
00991                 xio->currentReadChunkSize=-1;
00992                 xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
00993               }
00994             }
00995           }
00996         } /* if there is no outbound read request */
00997       } /* if inbound request not yet fullfilled */
00998     } /* if not finished */
00999   } /* if there is an inbound read request */
01000 
01001   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01002 }
01003 
01004 
01005 
01006 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest(GWEN_IO_LAYER *io) {
01007   GWEN_IO_LAYER_HTTP *xio;
01008 
01009   assert(io);
01010   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01011   assert(xio);
01012 
01013   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest (%d)", xio->readMode);
01014 
01015   switch(xio->readMode) {
01016   case GWEN_Io_LayerHttp_Mode_Command:
01017   case GWEN_Io_LayerHttp_Mode_Status:
01018   case GWEN_Io_LayerHttp_Mode_Header:
01019   case GWEN_Io_LayerHttp_Mode_ChunkSize:
01020     return GWEN_Io_LayerHttp_WorkOnReadRequest1(io);
01021 
01022   case GWEN_Io_LayerHttp_Mode_Chunk:
01023   case GWEN_Io_LayerHttp_Mode_Body:
01024   case GWEN_Io_LayerHttp_Mode_Finished:
01025   default:
01026     return GWEN_Io_LayerHttp_WorkOnReadRequest2(io);
01027   }
01028 }
01029 
01030 
01031 
01032 /* writing command/status/header */
01033 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest1(GWEN_IO_LAYER *io) {
01034   GWEN_IO_LAYER_HTTP *xio;
01035   int doneSomething=0;
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_WorkOnWriteRequest1 (%d)", xio->writeMode);
01042 
01043   if (xio->writeRequestOut) {
01044     if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
01045       GWEN_IO_REQUEST *rOut;
01046       uint32_t bposOut;
01047       uint32_t flagsOut;
01048 
01049       rOut=xio->writeRequestOut;
01050       flagsOut=GWEN_Io_Request_GetFlags(rOut);
01051       bposOut=GWEN_Io_Request_GetBufferPos(rOut);
01052 
01053       DBG_VERBOUS(GWEN_LOGDOMAIN, "Sent %d bytes", bposOut);
01054 
01055       GWEN_Buffer_IncrementPos(xio->writeBuffer, bposOut);
01056       xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(xio->writeRequestOut);
01057 
01058       /* delete outbound request */
01059       GWEN_Io_Request_free(xio->writeRequestOut);
01060       xio->writeRequestOut=NULL;
01061 
01062       doneSomething=1;
01063     }
01064   }
01065 
01066   if (xio->writeRequestIn) {
01067     GWEN_IO_REQUEST *rIn;
01068 
01069     rIn=xio->writeRequestIn;
01070     if (GWEN_Buffer_GetBytesLeft(xio->writeBuffer)) {
01071       if (xio->writeRequestOut==NULL) {
01072         if (xio->lastWriteOutResult) {
01073           xio->writeRequestIn=NULL;
01074           DBG_INFO(GWEN_LOGDOMAIN,
01075                    "Aborting in write request (reason: %d)",
01076                    xio->lastWriteOutResult);
01077           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastWriteOutResult);
01078           GWEN_Io_Request_free(rIn);
01079           rIn=NULL;
01080           doneSomething=1;
01081         }
01082         else {
01083           GWEN_IO_REQUEST *rOut;
01084           int rv;
01085 
01086           DBG_VERBOUS(GWEN_LOGDOMAIN, "Sending %d header bytes", GWEN_Buffer_GetBytesLeft(xio->writeBuffer));
01087           rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
01088                                    (uint8_t*)GWEN_Buffer_GetPosPointer(xio->writeBuffer),
01089                                    GWEN_Buffer_GetBytesLeft(xio->writeBuffer),
01090                                    NULL, NULL,
01091                                    GWEN_Io_Request_GetGuiId(rIn));
01092           GWEN_Io_Request_AddFlags(rOut,
01093                                    GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW |
01094                                    GWEN_IO_REQUEST_FLAGS_FLUSH |
01095                                    GWEN_IO_REQUEST_FLAGS_WRITEALL);
01096           rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
01097           if (rv) {
01098             GWEN_Io_Request_free(rOut);
01099             if (rv!=GWEN_ERROR_TRY_AGAIN) {
01100               xio->lastWriteOutResult=rv;
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, rv);
01106               GWEN_Io_Request_free(rIn);
01107               rIn=NULL;
01108               doneSomething=1;
01109             }
01110           }
01111           else {
01112             xio->writeRequestOut=rOut;
01113             doneSomething=1;
01114           }
01115         } /* if lastOutResult was ok */
01116       } /* if there is no outbound request */
01117     } /* if there still are bytes in the buffer to write */
01118     else {
01119       /* header finished, prepare writing of the body */
01120       GWEN_Buffer_Reset(xio->writeBuffer);
01121       if (xio->currentWriteBodySize!=0)
01122         /* header finished, body follows */
01123         xio->writeMode=GWEN_Io_LayerHttp_Mode_Body;
01124       else
01125         /* no body */
01126         xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01127     }
01128   } /* if there is an inbound request */
01129 
01130 
01131   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01132 }
01133 
01134 
01135 
01136 /* writing body/ finished*/
01137 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest2(GWEN_IO_LAYER *io) {
01138   GWEN_IO_LAYER_HTTP *xio;
01139   int doneSomething=0;
01140 
01141   assert(io);
01142   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01143   assert(xio);
01144 
01145   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest2 (%d)", xio->writeMode);
01146 
01147   if (xio->writeRequestOut) {
01148     if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
01149       GWEN_IO_REQUEST *rOut;
01150 
01151       doneSomething=1;
01152       rOut=xio->writeRequestOut;
01153       if (xio->writeRequestIn) {
01154         uint32_t bposOut;
01155         uint32_t flagsOut;
01156         GWEN_IO_REQUEST *rIn;
01157         uint32_t bposIn;
01158         uint32_t flagsIn;
01159 
01160         rOut=xio->writeRequestOut;
01161         flagsOut=GWEN_Io_Request_GetFlags(rOut);
01162         bposOut=GWEN_Io_Request_GetBufferPos(rOut);
01163 
01164         rIn=xio->writeRequestIn;
01165         flagsIn=GWEN_Io_Request_GetFlags(rIn);
01166         bposIn=GWEN_Io_Request_GetBufferPos(rIn)+bposOut;
01167         GWEN_Io_Request_SetBufferPos(rIn, bposIn);
01168 
01169         DBG_VERBOUS(GWEN_LOGDOMAIN, "Sent %d body bytes (%d)",
01170                     bposOut, GWEN_Io_Request_GetResultCode(rOut));
01171 
01172         /* get last result */
01173         xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(rOut);
01174 
01175         /* delete outbound request */
01176         GWEN_Io_Request_free(xio->writeRequestOut);
01177         xio->writeRequestOut=NULL;
01178 
01179         if (xio->currentWriteBodySize!=-1)
01180           xio->currentWriteBodySize-=bposOut;
01181 
01182         /* check whether the body has been finished */
01183         if (xio->currentWriteBodySize==0) {
01184           /* body finished (in any mode) */
01185           GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
01186           xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01187           if (bposIn<GWEN_Io_Request_GetBufferSize(rIn) &&
01188               (flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL)) {
01189             /* body finished, but caller insists on writing more data, abort */
01190             xio->writeRequestIn=NULL;
01191             DBG_INFO(GWEN_LOGDOMAIN,
01192                      "Aborting in write request (reason: %d)",
01193                      GWEN_ERROR_BAD_SIZE);
01194             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_SIZE);
01195             GWEN_Io_Request_free(rIn);
01196             rIn=NULL;
01197           }
01198         }
01199         else {
01200           /* body not complete (or unknown) */
01201           if (bposIn>=GWEN_Io_Request_GetBufferSize(rIn) ||
01202               (bposIn && !(flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL))) {
01203             /* inbound request fullfilled */
01204             xio->writeRequestIn=NULL;
01205             GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
01206             GWEN_Io_Request_free(rIn);
01207             rIn=NULL;
01208           }
01209         }
01210       }
01211     }
01212   }
01213 
01214   if (xio->writeRequestIn) {
01215     GWEN_IO_REQUEST *rIn;
01216 
01217     rIn=xio->writeRequestIn;
01218     if (xio->writeRequestOut==NULL) {
01219       if (xio->lastWriteOutResult) {
01220         xio->writeRequestIn=NULL;
01221         DBG_INFO(GWEN_LOGDOMAIN,
01222                  "Aborting in write request (reason: %d)",
01223                  xio->lastWriteOutResult);
01224         GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastWriteOutResult);
01225         GWEN_Io_Request_free(rIn);
01226         rIn=NULL;
01227         doneSomething=1;
01228       }
01229       else {
01230         int len;
01231         int bpos;
01232 
01233         /* create new write request for remaining bytes */
01234         bpos=GWEN_Io_Request_GetBufferPos(rIn);
01235         len=GWEN_Io_Request_GetBufferSize(rIn)-bpos;
01236         if (xio->currentWriteBodySize!=-1 && len>xio->currentWriteBodySize)
01237           /* adapt number of bytes to write */
01238           len=xio->currentWriteBodySize;
01239 
01240         if (len==0) {
01241           if (xio->currentWriteBodySize==0)
01242             GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
01243           xio->writeRequestIn=NULL;
01244           GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
01245           GWEN_Io_Request_free(rIn);
01246           rIn=NULL;
01247           doneSomething=1;
01248         }
01249         else {
01250           GWEN_IO_REQUEST *rOut;
01251           int rv;
01252 
01253           /* create new write request for remaining bytes */
01254           DBG_VERBOUS(GWEN_LOGDOMAIN, "Sending %d body bytes", len);
01255           rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
01256                                    GWEN_Io_Request_GetBufferPtr(rIn)+bpos, len,
01257                                    NULL, NULL,
01258                                    GWEN_Io_Request_GetGuiId(rIn));
01259           GWEN_Io_Request_AddFlags(rOut,
01260                                    GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW |
01261                                    GWEN_IO_REQUEST_FLAGS_FLUSH |
01262                                    GWEN_IO_REQUEST_FLAGS_WRITEALL);
01263           rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
01264           if (rv) {
01265             GWEN_Io_Request_free(rOut);
01266             if (rv!=GWEN_ERROR_TRY_AGAIN) {
01267               xio->lastWriteOutResult=rv;
01268               xio->writeRequestIn=NULL;
01269               DBG_INFO(GWEN_LOGDOMAIN,
01270                        "Aborting in write request (reason: %d)",
01271                        xio->lastWriteOutResult);
01272               GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01273               GWEN_Io_Request_free(rIn);
01274               rIn=NULL;
01275               doneSomething=1;
01276             }
01277           }
01278           else {
01279             xio->writeRequestOut=rOut;
01280             doneSomething=1;
01281           }
01282         }
01283       } /* if lastOutResult was ok */
01284     }
01285 
01286 
01287   } /* if there is an inbound request */
01288 
01289 
01290   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01291 }
01292 
01293 
01294 
01295 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest(GWEN_IO_LAYER *io) {
01296   GWEN_IO_LAYER_HTTP *xio;
01297 
01298   assert(io);
01299   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01300   assert(xio);
01301 
01302   DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest (%d)", xio->writeMode);
01303 
01304   switch(xio->writeMode) {
01305   case GWEN_Io_LayerHttp_Mode_Command:
01306   case GWEN_Io_LayerHttp_Mode_Status:
01307   case GWEN_Io_LayerHttp_Mode_Header:
01308   case GWEN_Io_LayerHttp_Mode_ChunkSize:
01309     return GWEN_Io_LayerHttp_WorkOnWriteRequest1(io);
01310 
01311   case GWEN_Io_LayerHttp_Mode_Chunk:
01312   case GWEN_Io_LayerHttp_Mode_Body:
01313   case GWEN_Io_LayerHttp_Mode_Finished:
01314   default:
01315     return GWEN_Io_LayerHttp_WorkOnWriteRequest2(io);
01316   }
01317 }
01318 
01319 
01320 
01321 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnRequests(GWEN_IO_LAYER *io) {
01322   GWEN_IO_LAYER_HTTP *xio;
01323   int doneSomething=0;
01324 
01325   assert(io);
01326   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01327   assert(xio);
01328 
01329   /* work on read request */
01330   if (GWEN_Io_LayerHttp_WorkOnReadRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01331     doneSomething=1;
01332 
01333   /* work on write request */
01334   if (GWEN_Io_LayerHttp_WorkOnWriteRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01335     doneSomething=1;
01336 
01337   /* let base layer work */
01338   if (GWEN_Io_Layer_WorkOnRequests(GWEN_Io_Layer_GetBaseLayer(io))!=GWEN_Io_Layer_WorkResultBlocking)
01339     doneSomething=1;
01340 
01341   if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
01342     GWEN_IO_LAYER *newIo;
01343 
01344     newIo=GWEN_Io_Layer_GetNextIncomingLayer(GWEN_Io_Layer_GetBaseLayer(io));
01345     if (newIo) {
01346       GWEN_IO_LAYER *newNewIo;
01347       GWEN_DB_NODE *dbSrc;
01348       GWEN_DB_NODE *dbDst;
01349       uint32_t fl;
01350 
01351       fl=GWEN_Io_Layer_GetFlags(io);
01352       newNewIo=GWEN_Io_LayerHttp_new(newIo);
01353       GWEN_Io_Layer_AddFlags(newNewIo, GWEN_IO_LAYER_FLAGS_PASSIVE);
01354       GWEN_Io_Layer_AddFlags(newNewIo, fl & 0xffff);
01355       /* copy command */
01356       dbDst=GWEN_Io_LayerHttp_GetDbCommandOut(newNewIo);
01357       dbSrc=xio->dbCommandOut;
01358       GWEN_DB_AddGroupChildren(dbDst, dbSrc);
01359 
01360       GWEN_Io_Layer_AddIncomingLayer(io, newNewIo);
01361       doneSomething=1;
01362     }
01363   }
01364 
01365   return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01366 }
01367 
01368 
01369 
01370 
01371 int GWEN_Io_LayerHttp_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01372   GWEN_IO_LAYER_HTTP *xio;
01373   GWEN_IO_LAYER_STATUS st;
01374   uint32_t lflags;
01375   uint32_t rflags;
01376 
01377   assert(io);
01378   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01379   assert(xio);
01380 
01381   st=GWEN_Io_Layer_GetStatus(io);
01382   lflags=GWEN_Io_Layer_GetFlags(io);
01383   rflags=GWEN_Io_Request_GetFlags(r);
01384 
01385   switch(GWEN_Io_Request_GetType(r)) {
01386   case GWEN_Io_Request_TypeRead:
01387     /* check status */
01388     if (st!=GWEN_Io_Layer_StatusConnected) {
01389       DBG_INFO(GWEN_LOGDOMAIN, "Layer not connected (%d)", st);
01390       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01391       return GWEN_ERROR_NOT_OPEN;
01392     }
01393 
01394     if (xio->lastReadOutResult) {
01395       DBG_INFO(GWEN_LOGDOMAIN, "Unable to read (%d)", xio->lastReadOutResult);
01396       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
01397       return xio->lastReadOutResult;
01398     }
01399 
01400     /* check whether we already have a read request */
01401     if (xio->readRequestIn) {
01402       DBG_INFO(GWEN_LOGDOMAIN, "There already is a read request");
01403       return GWEN_ERROR_TRY_AGAIN;
01404     }
01405 
01406     if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETBEGIN) {
01407       if (xio->readMode!=GWEN_Io_LayerHttp_Mode_Idle) {
01408         DBG_INFO(GWEN_LOGDOMAIN, "Packetbegin requested while there is still a packet in work");
01409         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01410         return GWEN_ERROR_INVALID;
01411       }
01412 
01413       GWEN_Buffer_Reset(xio->readBuffer);
01414       GWEN_DB_ClearGroup(xio->dbCommandIn, NULL);
01415       GWEN_DB_ClearGroup(xio->dbStatusIn, NULL);
01416       GWEN_DB_ClearGroup(xio->dbHeaderIn, NULL);
01417       xio->currentReadChunkSize=-1;
01418       xio->currentReadBodySize=-1;
01419       xio->readLineFinished=0;
01420       if ((lflags & GWEN_IO_LAYER_HTTP_FLAGS_IPC) ||
01421           (lflags & GWEN_IO_LAYER_FLAGS_PASSIVE))
01422         xio->readMode=GWEN_Io_LayerHttp_Mode_Command;
01423       else
01424         xio->readMode=GWEN_Io_LayerHttp_Mode_Status;
01425     }
01426     else {
01427       if (xio->readMode!=GWEN_Io_LayerHttp_Mode_ChunkSize &&
01428           xio->readMode!=GWEN_Io_LayerHttp_Mode_Chunk &&
01429           xio->readMode!=GWEN_Io_LayerHttp_Mode_Body) {
01430         DBG_INFO(GWEN_LOGDOMAIN, "Bad read mode and flag GWEN_IO_REQUEST_FLAGS_PACKETBEGIN not set");
01431         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01432         return GWEN_ERROR_INVALID;
01433       }
01434     }
01435 
01436     /* enqueue request */
01437     xio->readRequestIn=r;
01438     GWEN_Io_Request_Attach(xio->readRequestIn);
01439     break;
01440 
01441   case GWEN_Io_Request_TypeWrite:
01442     /* check status */
01443     if (st!=GWEN_Io_Layer_StatusConnected) {
01444       DBG_INFO(GWEN_LOGDOMAIN, "Layer is not connected");
01445       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01446       return GWEN_ERROR_NOT_OPEN;
01447     }
01448 
01449     /* check whether we already have a read request */
01450     if (xio->writeRequestIn) {
01451       DBG_INFO(GWEN_LOGDOMAIN, "There already is a write request");
01452       return GWEN_ERROR_TRY_AGAIN;
01453     }
01454 
01455     if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETBEGIN) {
01456       int rv;
01457 
01458       if (xio->writeMode!=GWEN_Io_LayerHttp_Mode_Idle && xio->writeMode!=GWEN_Io_LayerHttp_Mode_Finished) {
01459         DBG_INFO(GWEN_LOGDOMAIN, "Packetbegin requested while there is still a packet in work");
01460         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01461         return GWEN_ERROR_INVALID;
01462       }
01463 
01464       DBG_VERBOUS(GWEN_LOGDOMAIN, "Packet begin");
01465       GWEN_Buffer_Reset(xio->writeBuffer);
01466       /* Write command/status */
01467       if ((lflags & GWEN_IO_LAYER_HTTP_FLAGS_IPC) ||
01468           !(lflags & GWEN_IO_LAYER_FLAGS_PASSIVE)) {
01469         rv=GWEN_Io_LayerHttp_WriteCommand(io, xio->writeBuffer);
01470         xio->writeMode=GWEN_Io_LayerHttp_Mode_Command;
01471       }
01472       else {
01473         rv=GWEN_Io_LayerHttp_WriteStatus(io, xio->writeBuffer);
01474         xio->writeMode=GWEN_Io_LayerHttp_Mode_Status;
01475       }
01476       if (rv<0) {
01477         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01478         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
01479         xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01480         return rv;
01481       }
01482 
01483       if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETEND)
01484         /* both flags packet begin and end are given, so we already know the content-length */
01485         GWEN_DB_SetIntValue(xio->dbHeaderOut, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-length",
01486                             GWEN_Io_Request_GetBufferSize(r));
01487 
01488       /* write header into buffer, get body size */
01489       rv=GWEN_Io_LayerHttp_WriteHeader(io, xio->writeBuffer);
01490       if (rv<0) {
01491         DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01492         GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
01493         xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01494         return rv;
01495       }
01496       GWEN_Buffer_Rewind(xio->writeBuffer);
01497       xio->writeMode=GWEN_Io_LayerHttp_Mode_Header;
01498       DBG_VERBOUS(GWEN_LOGDOMAIN, "Buffer: %d/%d",
01499                   GWEN_Buffer_GetBytesLeft(xio->writeBuffer),
01500                   GWEN_Buffer_GetUsedBytes(xio->writeBuffer));
01501     }
01502     else {
01503       if (xio->writeMode!=GWEN_Io_LayerHttp_Mode_Body) {
01504         if ((GWEN_Io_Request_GetBufferSize(r)==0) &&
01505             (rflags & GWEN_IO_REQUEST_FLAGS_FLUSH)) {
01506           /* this is just a flush request */
01507           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01508           return 0;
01509         }
01510         else {
01511           DBG_INFO(GWEN_LOGDOMAIN, "Bad write mode and flag GWEN_IO_REQUEST_FLAGS_PACKETBEGIN not set");
01512           GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01513           return GWEN_ERROR_INVALID;
01514         }
01515       }
01516     }
01517 
01518     /* enqueue request */
01519     xio->writeRequestIn=r;
01520     GWEN_Io_Request_Attach(xio->writeRequestIn);
01521     break;
01522 
01523   case GWEN_Io_Request_TypeConnect:
01524     /* check status */
01525     if (st!=GWEN_Io_Layer_StatusUnconnected &&
01526         st!=GWEN_Io_Layer_StatusDisconnected) {
01527       DBG_INFO(GWEN_LOGDOMAIN, "Layer not un-/disconnected");
01528       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01529       return GWEN_ERROR_NOT_OPEN;
01530     }
01531     else {
01532       /* reset all structures */
01533       xio->lastReadOutResult=0;
01534       GWEN_Buffer_Reset(xio->readBuffer);
01535       xio->readMode=GWEN_Io_LayerHttp_Mode_Idle;
01536       xio->currentReadChunkSize=-1;
01537       xio->currentReadBodySize=-1;
01538       xio->readLineFinished=0;
01539 
01540       xio->lastWriteOutResult=0;
01541       GWEN_Buffer_Reset(xio->writeBuffer);
01542       xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01543 
01544       GWEN_DB_ClearGroup(xio->dbCommandIn, NULL);
01545       GWEN_DB_ClearGroup(xio->dbStatusIn, NULL);
01546       GWEN_DB_ClearGroup(xio->dbHeaderIn, NULL);
01547 
01548       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
01549       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01550       DBG_INFO(GWEN_LOGDOMAIN, "Layer now connected");
01551     }
01552     break;
01553 
01554   case GWEN_Io_Request_TypeDisconnect:
01555     /* check status */
01556     if (st!=GWEN_Io_Layer_StatusConnected) {
01557       DBG_INFO(GWEN_LOGDOMAIN, "IO layer is not open");
01558       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01559       return GWEN_ERROR_NOT_OPEN;
01560     }
01561     else {
01562       /* abort incoming requests, if any */
01563       GWEN_Io_LayerHttp_AbortInRequests(io, GWEN_ERROR_ABORTED);
01564       GWEN_Io_LayerHttp_AbortOutRequests(io);
01565 
01566       /* closed */
01567       GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01568       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01569     }
01570     break;
01571 
01572   default:
01573     DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
01574     GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
01575     return GWEN_ERROR_NOT_SUPPORTED;
01576   }
01577 
01578   return 0;
01579 }
01580 
01581 
01582 
01583 int GWEN_Io_LayerHttp_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01584   GWEN_IO_LAYER_HTTP *xio;
01585 
01586   assert(io);
01587   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01588   assert(xio);
01589 
01590   switch(GWEN_Io_Request_GetType(r)) {
01591   case GWEN_Io_Request_TypeRead:
01592     if (xio->readRequestIn==r) {
01593       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted read request");
01594       xio->readRequestIn=NULL;
01595       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01596       GWEN_Io_Request_free(r);
01597     }
01598     else {
01599       /* not my request */
01600       DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
01601       return GWEN_ERROR_INVALID;
01602     }
01603     break;
01604 
01605   case GWEN_Io_Request_TypeWrite:
01606     if (xio->writeRequestIn==r) {
01607       DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted write request");
01608       xio->writeRequestIn=NULL;
01609       GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01610       GWEN_Io_Request_free(r);
01611     }
01612     else {
01613       /* not my request */
01614       DBG_INFO(GWEN_LOGDOMAIN, "Write request not registered with this io layer");
01615       return GWEN_ERROR_INVALID;
01616     }
01617     break;
01618 
01619   default:
01620     break;
01621   }
01622 
01623   return 0;
01624 }
01625 
01626 
01627 
01628 int GWEN_Io_LayerHttp_HasWaitingRequests(GWEN_IO_LAYER *io) {
01629   GWEN_IO_LAYER_HTTP *xio;
01630 
01631   assert(io);
01632   xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01633   assert(xio);
01634 
01635   if (xio->readRequestIn || xio->writeRequestIn)
01636     return 1;
01637   else
01638     return 0;
01639 }
01640 
01641 
01642 
01643 
01644 
01645 

Generated on Fri Apr 11 01:53:47 2008 for gwenhywfar by  doxygen 1.5.5