00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #ifdef HAVE_CONFIG_H
00014 # include <config.h>
00015 #endif
00016
00017
00018 #include "io_http_p.h"
00019 #include <gwenhywfar/iolayer_be.h>
00020 #include <gwenhywfar/iorequest_be.h>
00021 #include <gwenhywfar/iomanager.h>
00022 #include <gwenhywfar/io_buffered.h>
00023
00024 #include "i18n_l.h"
00025 #include <gwenhywfar/misc.h>
00026 #include <gwenhywfar/debug.h>
00027 #include <gwenhywfar/gui.h>
00028 #include <gwenhywfar/text.h>
00029
00030 #include <assert.h>
00031 #include <ctype.h>
00032
00033
00034
00035
00036 GWEN_INHERIT(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP)
00037
00038
00039
00040
00041
00042 GWEN_IO_LAYER *GWEN_Io_LayerHttp_new(GWEN_IO_LAYER *baseLayer) {
00043 GWEN_IO_LAYER *io;
00044 GWEN_IO_LAYER_HTTP *xio;
00045
00046 io=GWEN_Io_Layer_new(GWEN_IO_LAYER_HTTP_TYPE, baseLayer);
00047 assert(io);
00048 GWEN_NEW_OBJECT(GWEN_IO_LAYER_HTTP, xio);
00049 assert(xio);
00050 GWEN_INHERIT_SETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io, xio, GWEN_Io_LayerHttp_freeData);
00051
00052 xio->dbCommandIn=GWEN_DB_Group_new("command");
00053 xio->dbStatusIn=GWEN_DB_Group_new("status");
00054 xio->dbHeaderIn=GWEN_DB_Group_new("header");
00055 xio->readBuffer=GWEN_Buffer_new(0, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE, 0, 1);
00056
00057 xio->dbCommandOut=GWEN_DB_Group_new("command");
00058 xio->dbStatusOut=GWEN_DB_Group_new("status");
00059 xio->dbHeaderOut=GWEN_DB_Group_new("header");
00060 xio->writeBuffer=GWEN_Buffer_new(0, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE, 0, 1);
00061
00062 GWEN_Io_Layer_SetWorkOnRequestsFn(io, GWEN_Io_LayerHttp_WorkOnRequests);
00063 GWEN_Io_Layer_SetAddRequestFn(io, GWEN_Io_LayerHttp_AddRequest);
00064 GWEN_Io_Layer_SetDelRequestFn(io, GWEN_Io_LayerHttp_DelRequest);
00065 GWEN_Io_Layer_SetHasWaitingRequestsFn(io, GWEN_Io_LayerHttp_HasWaitingRequests);
00066
00067 return io;
00068 }
00069
00070
00071
00072 GWENHYWFAR_CB
00073 void GWEN_Io_LayerHttp_freeData(GWEN_UNUSED void *bp, void *p) {
00074 GWEN_IO_LAYER_HTTP *xio;
00075
00076 xio=(GWEN_IO_LAYER_HTTP*) p;
00077 GWEN_DB_Group_free(xio->dbCommandIn);
00078 GWEN_DB_Group_free(xio->dbStatusIn);
00079 GWEN_DB_Group_free(xio->dbHeaderIn);
00080 GWEN_Buffer_free(xio->readBuffer);
00081
00082 GWEN_DB_Group_free(xio->dbCommandOut);
00083 GWEN_DB_Group_free(xio->dbStatusOut);
00084 GWEN_DB_Group_free(xio->dbHeaderOut);
00085 GWEN_Buffer_free(xio->writeBuffer);
00086
00087 GWEN_FREE_OBJECT(xio);
00088 }
00089
00090
00091
00092 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbCommandIn(const GWEN_IO_LAYER *io) {
00093 GWEN_IO_LAYER_HTTP *xio;
00094
00095 assert(io);
00096 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00097 assert(xio);
00098
00099 return xio->dbCommandIn;
00100 }
00101
00102
00103
00104 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbStatusIn(const GWEN_IO_LAYER *io) {
00105 GWEN_IO_LAYER_HTTP *xio;
00106
00107 assert(io);
00108 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00109 assert(xio);
00110
00111 return xio->dbStatusIn;
00112 }
00113
00114
00115
00116 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbHeaderIn(const GWEN_IO_LAYER *io) {
00117 GWEN_IO_LAYER_HTTP *xio;
00118
00119 assert(io);
00120 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00121 assert(xio);
00122
00123 return xio->dbHeaderIn;
00124 }
00125
00126
00127
00128 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbCommandOut(const GWEN_IO_LAYER *io) {
00129 GWEN_IO_LAYER_HTTP *xio;
00130
00131 assert(io);
00132 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00133 assert(xio);
00134
00135 return xio->dbCommandOut;
00136 }
00137
00138
00139
00140 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbStatusOut(const GWEN_IO_LAYER *io) {
00141 GWEN_IO_LAYER_HTTP *xio;
00142
00143 assert(io);
00144 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00145 assert(xio);
00146
00147 return xio->dbStatusOut;
00148 }
00149
00150
00151
00152 GWEN_DB_NODE *GWEN_Io_LayerHttp_GetDbHeaderOut(const GWEN_IO_LAYER *io) {
00153 GWEN_IO_LAYER_HTTP *xio;
00154
00155 assert(io);
00156 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00157 assert(xio);
00158
00159 return xio->dbHeaderOut;
00160 }
00161
00162
00163
00164 void GWEN_Io_LayerHttp_AbortInRequests(GWEN_IO_LAYER *io, int errorCode) {
00165 GWEN_IO_LAYER_HTTP *xio;
00166
00167 assert(io);
00168 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00169 assert(xio);
00170
00171 if (xio->readRequestIn) {
00172 GWEN_IO_REQUEST *r;
00173
00174 r=xio->readRequestIn;
00175 xio->readRequestIn=NULL;
00176 DBG_INFO(GWEN_LOGDOMAIN, "Aborting in read request");
00177 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00178 GWEN_Io_Request_free(r);
00179 }
00180 if (xio->writeRequestIn) {
00181 GWEN_IO_REQUEST *r;
00182
00183 r=xio->writeRequestIn;
00184 xio->writeRequestIn=NULL;
00185 DBG_INFO(GWEN_LOGDOMAIN, "Aborting in write request");
00186 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, errorCode);
00187 GWEN_Io_Request_free(r);
00188 }
00189 }
00190
00191
00192
00193 void GWEN_Io_LayerHttp_AbortOutRequests(GWEN_IO_LAYER *io) {
00194 GWEN_IO_LAYER_HTTP *xio;
00195
00196 assert(io);
00197 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00198 assert(xio);
00199
00200 if (xio->readRequestOut) {
00201 GWEN_IO_REQUEST *r;
00202
00203 r=xio->readRequestOut;
00204 GWEN_Io_Layer_DelRequest(GWEN_Io_Layer_GetBaseLayer(io), r);
00205 xio->readRequestOut=NULL;
00206 GWEN_Io_Request_free(r);
00207 }
00208 if (xio->writeRequestIn) {
00209 GWEN_IO_REQUEST *r;
00210
00211 r=xio->writeRequestIn;
00212 GWEN_Io_Layer_DelRequest(GWEN_Io_Layer_GetBaseLayer(io), r);
00213 xio->writeRequestIn=NULL;
00214 GWEN_Io_Request_free(r);
00215 }
00216 }
00217
00218
00219
00220
00221
00222 int GWEN_Io_LayerHttp_ParseCommand(GWEN_IO_LAYER *io, const char *buffer) {
00223 GWEN_IO_LAYER_HTTP *xio;
00224 char *tmp;
00225 char *p;
00226 char *s;
00227
00228 assert(io);
00229 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00230 assert(xio);
00231
00232 tmp=strdup(buffer);
00233 s=tmp;
00234
00235
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
00250 p=strchr(s, ' ');
00251 if (!p) {
00252
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
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
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
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
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
00349 p=buf;
00350 while(*p) {
00351 p=strchr(p, 10);
00352 if (p) {
00353 if (p[1]==32 || p[1]==9)
00354
00355 *p=32;
00356 p++;
00357 }
00358 }
00359
00360
00361 p=buf;
00362 while(p && *p) {
00363 char *pNext;
00364 char *pVarBegin;
00365 char *pVarEnd;
00366
00367
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
00396
00397 xio->readMode=GWEN_Io_LayerHttp_Mode_Body;
00398
00399
00400 s=GWEN_DB_GetCharValue(xio->dbHeaderIn, "Transfer-Encoding", 0, 0);
00401 if (s && (-1!=GWEN_Text_ComparePattern(s, "*chunked*", 0))) {
00402
00403 xio->currentReadChunkSize=-1;
00404 xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
00405 }
00406
00407
00408 xio->currentReadBodySize=GWEN_DB_GetIntValue(xio->dbHeaderIn, "Content-Length", 0, -1);
00409 if (xio->currentReadBodySize==0) {
00410
00411 xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00412 }
00413 if (xio->currentReadBodySize==-1) {
00414 int rcode;
00415
00416
00417
00418
00419
00420 rcode=GWEN_DB_GetIntValue(xio->dbStatusIn, "code", 0, -1);
00421 if (rcode<0 || rcode>=300) {
00422
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
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
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
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
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
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
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
00586 GWEN_Io_Request_free(xio->readRequestOut);
00587 xio->readRequestOut=NULL;
00588 }
00589 }
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 }
00650 }
00651 }
00652 }
00653 else {
00654 int rv;
00655
00656
00657 doneSomething=1;
00658 xio->readLineFinished=0;
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
00707 GWEN_Buffer_AppendByte(xio->readBuffer, 10);
00708 if ((i-xio->lastHeaderPos)==0) {
00709
00710
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;
00728 if (xio->readRequestOut==NULL) {
00729 if (xio->lastReadOutResult) {
00730 xio->readRequestIn=NULL;
00731 DBG_INFO(GWEN_LOGDOMAIN,
00732 "Aborting in read request (reason: %d)",
00733 xio->lastReadOutResult);
00734 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00735 GWEN_Io_Request_free(rIn);
00736 rIn=NULL;
00737 doneSomething=1;
00738 }
00739 else {
00740
00741 rv=GWEN_Buffer_AllocRoom(xio->readBuffer, GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00742 if (rv<0) {
00743 xio->readRequestIn=NULL;
00744 xio->lastReadOutResult=GWEN_ERROR_MEMORY_FULL;
00745 DBG_INFO(GWEN_LOGDOMAIN,
00746 "Aborting in read request (reason: %d)",
00747 xio->lastReadOutResult);
00748 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_MEMORY_FULL);
00749 GWEN_Io_Request_free(rIn);
00750 rIn=NULL;
00751 doneSomething=1;
00752 }
00753 else {
00754 GWEN_IO_REQUEST *rOut;
00755
00756 DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d header bytes", GWEN_IO_LAYER_HTTP_LINE_STEPSIZE);
00757 rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00758 (uint8_t*)GWEN_Buffer_GetPosPointer(xio->readBuffer),
00759 GWEN_IO_LAYER_HTTP_LINE_STEPSIZE,
00760 NULL, NULL,
00761 GWEN_Io_Request_GetGuiId(rIn));
00762 rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00763 if (rv) {
00764 if (rv!=GWEN_ERROR_TRY_AGAIN) {
00765 GWEN_Io_Request_free(rOut);
00766 xio->readRequestIn=NULL;
00767 xio->lastReadOutResult=rv;
00768 DBG_INFO(GWEN_LOGDOMAIN,
00769 "Aborting in read request (reason: %d)",
00770 xio->lastReadOutResult);
00771 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
00772 GWEN_Io_Request_free(rIn);
00773 rIn=NULL;
00774 doneSomething=1;
00775 }
00776 }
00777 else {
00778 DBG_DEBUG(GWEN_LOGDOMAIN, "Added header read request");
00779 xio->readRequestOut=rOut;
00780 doneSomething=1;
00781 }
00782 }
00783 }
00784 }
00785 }
00786 break;
00787 }
00788
00789 case GWEN_Io_LayerHttp_Mode_ChunkSize: {
00790 int csize;
00791
00792 if (GWEN_Buffer_GetUsedBytes(xio->readBuffer)==0) {
00793 DBG_INFO(GWEN_LOGDOMAIN, "Empty line, skipping");
00794 }
00795 else {
00796 if (1!=sscanf(GWEN_Buffer_GetStart(xio->readBuffer), "%x", &csize)) {
00797 DBG_INFO(GWEN_LOGDOMAIN, "Invalid chunksize [%s]", GWEN_Buffer_GetStart(xio->readBuffer));
00798 xio->lastReadOutResult=GWEN_ERROR_BAD_DATA;
00799 xio->readRequestIn=NULL;
00800 DBG_INFO(GWEN_LOGDOMAIN,
00801 "Aborting in read request (reason: %d)",
00802 xio->lastReadOutResult);
00803 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_DATA);
00804 GWEN_Io_Request_free(rIn);
00805 rIn=NULL;
00806 }
00807 else {
00808 xio->currentReadChunkSize=csize;
00809 DBG_DEBUG(GWEN_LOGDOMAIN, "Chunksize: %d", csize);
00810 if (csize==0) {
00811 DBG_DEBUG(GWEN_LOGDOMAIN, "Last chunk received");
00812 xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00813 GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00814 }
00815 else {
00816 DBG_DEBUG(GWEN_LOGDOMAIN, "Started reading next chunk (%d bytes)",
00817 csize);
00818 xio->readMode=GWEN_Io_LayerHttp_Mode_Chunk;
00819 }
00820 }
00821 }
00822 break;
00823 }
00824
00825 default:
00826
00827 assert(0);
00828 break;
00829 }
00830 }
00831 }
00832
00833 return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
00834 }
00835
00836
00837
00838 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest2(GWEN_IO_LAYER *io) {
00839 GWEN_IO_LAYER_HTTP *xio;
00840 int doneSomething=0;
00841
00842 assert(io);
00843 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
00844 assert(xio);
00845
00846 DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest2 (%d)", xio->readMode);
00847
00848 if (xio->readRequestOut) {
00849
00850 if (GWEN_Io_Request_GetStatus(xio->readRequestOut)==GWEN_Io_Request_StatusFinished) {
00851 GWEN_IO_REQUEST *rOut;
00852 uint32_t bposOut;
00853 uint32_t flagsOut;
00854
00855 rOut=xio->readRequestOut;
00856 flagsOut=GWEN_Io_Request_GetFlags(rOut);
00857 bposOut=GWEN_Io_Request_GetBufferPos(rOut);
00858
00859 doneSomething=1;
00860
00861 if (xio->readRequestIn) {
00862 GWEN_IO_REQUEST *rIn;
00863 uint32_t bposIn;
00864 uint32_t flagsIn;
00865
00866 rIn=xio->readRequestIn;
00867 flagsIn=GWEN_Io_Request_GetFlags(rIn);
00868 bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00869
00870 DBG_VERBOUS(GWEN_LOGDOMAIN, "Received %d (total: %d) bytes", bposIn, bposIn+bposOut);
00871
00872
00873 xio->lastReadOutResult=GWEN_Io_Request_GetResultCode(xio->readRequestOut);
00874
00875
00876 GWEN_Io_Request_free(xio->readRequestOut);
00877 xio->readRequestOut=NULL;
00878
00879
00880 bposIn+=bposOut;
00881 GWEN_Io_Request_SetBufferPos(rIn, bposIn);
00882
00883 if (xio->currentReadBodySize!=-1) {
00884 xio->currentReadBodySize-=bposOut;
00885 }
00886
00887 if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk) {
00888 xio->currentReadChunkSize-=bposOut;
00889 }
00890
00891 if (xio->currentReadBodySize==0) {
00892
00893 GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00894 xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
00895 }
00896 else {
00897 if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk && xio->currentReadChunkSize==0) {
00898
00899 DBG_DEBUG(GWEN_LOGDOMAIN, "Chunk finished");
00900 xio->currentReadChunkSize=-1;
00901 xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
00902 xio->readLineFinished=0;
00903 GWEN_Buffer_Reset(xio->readBuffer);
00904 doneSomething=1;
00905 }
00906 }
00907 }
00908 }
00909 }
00910
00911 if (xio->readRequestIn) {
00912 GWEN_IO_REQUEST *rIn;
00913 uint32_t flagsIn;
00914
00915 rIn=xio->readRequestIn;
00916 flagsIn=GWEN_Io_Request_GetFlags(rIn);
00917
00918 if (xio->readMode==GWEN_Io_LayerHttp_Mode_Finished) {
00919 uint32_t bposIn;
00920
00921 GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
00922 bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00923 if (bposIn<GWEN_Io_Request_GetBufferSize(rIn) &&
00924 (flagsIn & GWEN_IO_REQUEST_FLAGS_READALL)) {
00925
00926 xio->readRequestIn=NULL;
00927 DBG_INFO(GWEN_LOGDOMAIN,
00928 "Aborting in read request (reason: %d)",
00929 GWEN_ERROR_BAD_SIZE);
00930 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_SIZE);
00931 GWEN_Io_Request_free(rIn);
00932 rIn=NULL;
00933 }
00934 else {
00935
00936 xio->readRequestIn=NULL;
00937 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
00938 GWEN_Io_Request_free(rIn);
00939 rIn=NULL;
00940 }
00941 xio->readMode=GWEN_Io_LayerHttp_Mode_Idle;
00942 doneSomething=1;
00943 }
00944 else if (xio->readMode==GWEN_Io_LayerHttp_Mode_ChunkSize) {
00945
00946
00947 }
00948 else {
00949 uint32_t len;
00950 uint32_t bposIn;
00951
00952 bposIn=GWEN_Io_Request_GetBufferPos(rIn);
00953 len=GWEN_Io_Request_GetBufferSize(rIn)-bposIn;
00954 if (len==0) {
00955
00956 xio->readRequestIn=NULL;
00957 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
00958 GWEN_Io_Request_free(rIn);
00959 rIn=NULL;
00960 doneSomething=1;
00961 }
00962 else {
00963 if (xio->readRequestOut==NULL) {
00964 if (xio->lastReadOutResult) {
00965 xio->readRequestIn=NULL;
00966 DBG_INFO(GWEN_LOGDOMAIN,
00967 "Aborting in read request (reason: %d)",
00968 xio->lastReadOutResult);
00969 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
00970 GWEN_Io_Request_free(rIn);
00971 rIn=NULL;
00972 doneSomething=1;
00973 }
00974 else {
00975 if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk &&
00976 xio->currentReadChunkSize!=-1 &&
00977 len>xio->currentReadChunkSize)
00978 len=xio->currentReadChunkSize;
00979 else if (xio->readMode==GWEN_Io_LayerHttp_Mode_Body &&
00980 xio->currentReadBodySize!=-1 &&
00981 len>xio->currentReadBodySize)
00982 len=xio->currentReadBodySize;
00983
00984 if (len) {
00985 GWEN_IO_REQUEST *rOut;
00986 int rv;
00987
00988 DBG_VERBOUS(GWEN_LOGDOMAIN, "Reading %d body bytes (already have %d/%d)",
00989 len, bposIn, GWEN_Io_Request_GetBufferSize(rIn));
00990 rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeRead,
00991 GWEN_Io_Request_GetBufferPtr(rIn)+bposIn, len,
00992 NULL, NULL,
00993 GWEN_Io_Request_GetGuiId(rIn));
00994 GWEN_Io_Request_AddFlags(rOut, GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW);
00995 rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
00996 if (rv) {
00997 GWEN_Io_Request_free(rOut);
00998 if (rv!=GWEN_ERROR_TRY_AGAIN) {
00999 xio->lastReadOutResult=rv;
01000 xio->readRequestIn=NULL;
01001 DBG_INFO(GWEN_LOGDOMAIN,
01002 "Aborting in read request (reason: %d)",
01003 xio->lastReadOutResult);
01004 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01005 GWEN_Io_Request_free(rIn);
01006 rIn=NULL;
01007 doneSomething=1;
01008 }
01009 }
01010 else {
01011 xio->readRequestOut=rOut;
01012 doneSomething=1;
01013 }
01014 }
01015 else {
01016 if (xio->currentReadBodySize==0)
01017 xio->readMode=GWEN_Io_LayerHttp_Mode_Finished;
01018 if (xio->currentReadChunkSize==0) {
01019 xio->currentReadChunkSize=-1;
01020 xio->readMode=GWEN_Io_LayerHttp_Mode_ChunkSize;
01021 }
01022 }
01023 }
01024 }
01025 }
01026 }
01027 }
01028
01029 return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01030 }
01031
01032
01033
01034 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnReadRequest(GWEN_IO_LAYER *io) {
01035 GWEN_IO_LAYER_HTTP *xio;
01036
01037 assert(io);
01038 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01039 assert(xio);
01040
01041 DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnReadRequest (%d)", xio->readMode);
01042
01043 switch(xio->readMode) {
01044 case GWEN_Io_LayerHttp_Mode_Command:
01045 case GWEN_Io_LayerHttp_Mode_Status:
01046 case GWEN_Io_LayerHttp_Mode_Header:
01047 case GWEN_Io_LayerHttp_Mode_ChunkSize:
01048 return GWEN_Io_LayerHttp_WorkOnReadRequest1(io);
01049
01050 case GWEN_Io_LayerHttp_Mode_Chunk:
01051 case GWEN_Io_LayerHttp_Mode_Body:
01052 case GWEN_Io_LayerHttp_Mode_Finished:
01053 default:
01054 return GWEN_Io_LayerHttp_WorkOnReadRequest2(io);
01055 }
01056 }
01057
01058
01059
01060
01061 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest1(GWEN_IO_LAYER *io) {
01062 GWEN_IO_LAYER_HTTP *xio;
01063 int doneSomething=0;
01064
01065 assert(io);
01066 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01067 assert(xio);
01068
01069 DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest1 (%d)", xio->writeMode);
01070
01071 if (xio->writeRequestOut) {
01072 if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
01073 GWEN_IO_REQUEST *rOut;
01074 uint32_t bposOut;
01075 uint32_t flagsOut;
01076
01077 rOut=xio->writeRequestOut;
01078 flagsOut=GWEN_Io_Request_GetFlags(rOut);
01079 bposOut=GWEN_Io_Request_GetBufferPos(rOut);
01080
01081 DBG_VERBOUS(GWEN_LOGDOMAIN, "Sent %d bytes", bposOut);
01082
01083 GWEN_Buffer_IncrementPos(xio->writeBuffer, bposOut);
01084 xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(xio->writeRequestOut);
01085
01086
01087 GWEN_Io_Request_free(xio->writeRequestOut);
01088 xio->writeRequestOut=NULL;
01089
01090 doneSomething=1;
01091 }
01092 }
01093
01094 if (xio->writeRequestIn) {
01095 GWEN_IO_REQUEST *rIn;
01096
01097 rIn=xio->writeRequestIn;
01098 if (GWEN_Buffer_GetBytesLeft(xio->writeBuffer)) {
01099 if (xio->writeRequestOut==NULL) {
01100 if (xio->lastWriteOutResult) {
01101 xio->writeRequestIn=NULL;
01102 DBG_INFO(GWEN_LOGDOMAIN,
01103 "Aborting in write request (reason: %d)",
01104 xio->lastWriteOutResult);
01105 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastWriteOutResult);
01106 GWEN_Io_Request_free(rIn);
01107 rIn=NULL;
01108 doneSomething=1;
01109 }
01110 else {
01111 GWEN_IO_REQUEST *rOut;
01112 int rv;
01113
01114 DBG_VERBOUS(GWEN_LOGDOMAIN, "Sending %d header bytes", GWEN_Buffer_GetBytesLeft(xio->writeBuffer));
01115 rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
01116 (uint8_t*)GWEN_Buffer_GetPosPointer(xio->writeBuffer),
01117 GWEN_Buffer_GetBytesLeft(xio->writeBuffer),
01118 NULL, NULL,
01119 GWEN_Io_Request_GetGuiId(rIn));
01120 GWEN_Io_Request_AddFlags(rOut,
01121 GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW |
01122 GWEN_IO_REQUEST_FLAGS_FLUSH |
01123 GWEN_IO_REQUEST_FLAGS_WRITEALL);
01124 rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
01125 if (rv) {
01126 GWEN_Io_Request_free(rOut);
01127 if (rv!=GWEN_ERROR_TRY_AGAIN) {
01128 xio->lastWriteOutResult=rv;
01129 xio->writeRequestIn=NULL;
01130 DBG_INFO(GWEN_LOGDOMAIN,
01131 "Aborting in write request (reason: %d)",
01132 xio->lastWriteOutResult);
01133 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01134 GWEN_Io_Request_free(rIn);
01135 rIn=NULL;
01136 doneSomething=1;
01137 }
01138 }
01139 else {
01140 xio->writeRequestOut=rOut;
01141 doneSomething=1;
01142 }
01143 }
01144 }
01145 }
01146 else {
01147
01148 GWEN_Buffer_Reset(xio->writeBuffer);
01149 if (xio->currentWriteBodySize!=0)
01150
01151 xio->writeMode=GWEN_Io_LayerHttp_Mode_Body;
01152 else
01153
01154 xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01155 }
01156 }
01157
01158
01159 return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01160 }
01161
01162
01163
01164
01165 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest2(GWEN_IO_LAYER *io) {
01166 GWEN_IO_LAYER_HTTP *xio;
01167 int doneSomething=0;
01168
01169 assert(io);
01170 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01171 assert(xio);
01172
01173 DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest2 (%d)", xio->writeMode);
01174
01175 if (xio->writeRequestOut) {
01176 if (GWEN_Io_Request_GetStatus(xio->writeRequestOut)==GWEN_Io_Request_StatusFinished) {
01177 GWEN_IO_REQUEST *rOut;
01178
01179 doneSomething=1;
01180 rOut=xio->writeRequestOut;
01181 if (xio->writeRequestIn) {
01182 uint32_t bposOut;
01183 uint32_t flagsOut;
01184 GWEN_IO_REQUEST *rIn;
01185 uint32_t bposIn;
01186 uint32_t flagsIn;
01187
01188 rOut=xio->writeRequestOut;
01189 flagsOut=GWEN_Io_Request_GetFlags(rOut);
01190 bposOut=GWEN_Io_Request_GetBufferPos(rOut);
01191
01192 rIn=xio->writeRequestIn;
01193 flagsIn=GWEN_Io_Request_GetFlags(rIn);
01194 bposIn=GWEN_Io_Request_GetBufferPos(rIn)+bposOut;
01195 GWEN_Io_Request_SetBufferPos(rIn, bposIn);
01196
01197 DBG_VERBOUS(GWEN_LOGDOMAIN, "Sent %d body bytes (%d)",
01198 bposOut, GWEN_Io_Request_GetResultCode(rOut));
01199
01200
01201 xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(rOut);
01202
01203
01204 GWEN_Io_Request_free(xio->writeRequestOut);
01205 xio->writeRequestOut=NULL;
01206
01207 if (xio->currentWriteBodySize!=-1)
01208 xio->currentWriteBodySize-=bposOut;
01209
01210
01211 if (xio->currentWriteBodySize==0) {
01212
01213 GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
01214 xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01215 if (bposIn<GWEN_Io_Request_GetBufferSize(rIn) &&
01216 (flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL)) {
01217
01218 xio->writeRequestIn=NULL;
01219 DBG_INFO(GWEN_LOGDOMAIN,
01220 "Aborting in write request (reason: %d)",
01221 GWEN_ERROR_BAD_SIZE);
01222 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, GWEN_ERROR_BAD_SIZE);
01223 GWEN_Io_Request_free(rIn);
01224 rIn=NULL;
01225 }
01226 }
01227 else {
01228
01229 if (bposIn>=GWEN_Io_Request_GetBufferSize(rIn) ||
01230 (bposIn && !(flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL))) {
01231
01232 xio->writeRequestIn=NULL;
01233 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
01234 GWEN_Io_Request_free(rIn);
01235 rIn=NULL;
01236 }
01237 }
01238 }
01239 }
01240 }
01241
01242 if (xio->writeRequestIn) {
01243 GWEN_IO_REQUEST *rIn;
01244
01245 rIn=xio->writeRequestIn;
01246 if (xio->writeRequestOut==NULL) {
01247 if (xio->lastWriteOutResult) {
01248 xio->writeRequestIn=NULL;
01249 DBG_INFO(GWEN_LOGDOMAIN,
01250 "Aborting in write request (reason: %d)",
01251 xio->lastWriteOutResult);
01252 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, xio->lastWriteOutResult);
01253 GWEN_Io_Request_free(rIn);
01254 rIn=NULL;
01255 doneSomething=1;
01256 }
01257 else {
01258 int len;
01259 int bpos;
01260
01261
01262 bpos=GWEN_Io_Request_GetBufferPos(rIn);
01263 len=GWEN_Io_Request_GetBufferSize(rIn)-bpos;
01264 if (xio->currentWriteBodySize!=-1 && len>xio->currentWriteBodySize)
01265
01266 len=xio->currentWriteBodySize;
01267
01268 if (len==0) {
01269 if (xio->currentWriteBodySize==0)
01270 GWEN_Io_Request_AddFlags(rIn, GWEN_IO_REQUEST_FLAGS_PACKETEND);
01271 xio->writeRequestIn=NULL;
01272 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, 0);
01273 GWEN_Io_Request_free(rIn);
01274 rIn=NULL;
01275 doneSomething=1;
01276 }
01277 else {
01278 GWEN_IO_REQUEST *rOut;
01279 int rv;
01280
01281
01282 DBG_VERBOUS(GWEN_LOGDOMAIN, "Sending %d body bytes", len);
01283 rOut=GWEN_Io_Request_new(GWEN_Io_Request_TypeWrite,
01284 GWEN_Io_Request_GetBufferPtr(rIn)+bpos, len,
01285 NULL, NULL,
01286 GWEN_Io_Request_GetGuiId(rIn));
01287 GWEN_Io_Request_AddFlags(rOut,
01288 GWEN_IO_REQUEST_BUFFERED_FLAGS_RAW |
01289 GWEN_IO_REQUEST_FLAGS_FLUSH |
01290 GWEN_IO_REQUEST_FLAGS_WRITEALL);
01291 rv=GWEN_Io_Layer_AddRequest(GWEN_Io_Layer_GetBaseLayer(io), rOut);
01292 if (rv) {
01293 GWEN_Io_Request_free(rOut);
01294 if (rv!=GWEN_ERROR_TRY_AGAIN) {
01295 xio->lastWriteOutResult=rv;
01296 xio->writeRequestIn=NULL;
01297 DBG_INFO(GWEN_LOGDOMAIN,
01298 "Aborting in write request (reason: %d)",
01299 xio->lastWriteOutResult);
01300 GWEN_Io_Request_Finished(rIn, GWEN_Io_Request_StatusFinished, rv);
01301 GWEN_Io_Request_free(rIn);
01302 rIn=NULL;
01303 doneSomething=1;
01304 }
01305 }
01306 else {
01307 xio->writeRequestOut=rOut;
01308 doneSomething=1;
01309 }
01310 }
01311 }
01312 }
01313
01314
01315 }
01316
01317
01318 return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01319 }
01320
01321
01322
01323 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnWriteRequest(GWEN_IO_LAYER *io) {
01324 GWEN_IO_LAYER_HTTP *xio;
01325
01326 assert(io);
01327 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01328 assert(xio);
01329
01330 DBG_VERBOUS(GWEN_LOGDOMAIN, "GWEN_Io_LayerHttp_WorkOnWriteRequest (%d)", xio->writeMode);
01331
01332 switch(xio->writeMode) {
01333 case GWEN_Io_LayerHttp_Mode_Command:
01334 case GWEN_Io_LayerHttp_Mode_Status:
01335 case GWEN_Io_LayerHttp_Mode_Header:
01336 case GWEN_Io_LayerHttp_Mode_ChunkSize:
01337 return GWEN_Io_LayerHttp_WorkOnWriteRequest1(io);
01338
01339 case GWEN_Io_LayerHttp_Mode_Chunk:
01340 case GWEN_Io_LayerHttp_Mode_Body:
01341 case GWEN_Io_LayerHttp_Mode_Finished:
01342 default:
01343 return GWEN_Io_LayerHttp_WorkOnWriteRequest2(io);
01344 }
01345 }
01346
01347
01348
01349 GWEN_IO_LAYER_WORKRESULT GWEN_Io_LayerHttp_WorkOnRequests(GWEN_IO_LAYER *io) {
01350 GWEN_IO_LAYER_HTTP *xio;
01351 int doneSomething=0;
01352
01353 assert(io);
01354 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01355 assert(xio);
01356
01357
01358 if (GWEN_Io_LayerHttp_WorkOnReadRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01359 doneSomething=1;
01360
01361
01362 if (GWEN_Io_LayerHttp_WorkOnWriteRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01363 doneSomething=1;
01364
01365
01366 if (GWEN_Io_Layer_WorkOnRequests(GWEN_Io_Layer_GetBaseLayer(io))!=GWEN_Io_Layer_WorkResultBlocking)
01367 doneSomething=1;
01368
01369 if (GWEN_Io_Layer_GetStatus(io)==GWEN_Io_Layer_StatusListening) {
01370 GWEN_IO_LAYER *newIo;
01371
01372 newIo=GWEN_Io_Layer_GetNextIncomingLayer(GWEN_Io_Layer_GetBaseLayer(io));
01373 if (newIo) {
01374 GWEN_IO_LAYER *newNewIo;
01375 GWEN_DB_NODE *dbSrc;
01376 GWEN_DB_NODE *dbDst;
01377 uint32_t fl;
01378
01379 fl=GWEN_Io_Layer_GetFlags(io);
01380 newNewIo=GWEN_Io_LayerHttp_new(newIo);
01381 GWEN_Io_Layer_AddFlags(newNewIo, GWEN_IO_LAYER_FLAGS_PASSIVE);
01382 GWEN_Io_Layer_AddFlags(newNewIo, fl & 0xffff);
01383
01384 dbDst=GWEN_Io_LayerHttp_GetDbCommandOut(newNewIo);
01385 dbSrc=xio->dbCommandOut;
01386 GWEN_DB_AddGroupChildren(dbDst, dbSrc);
01387
01388 GWEN_Io_Layer_AddIncomingLayer(io, newNewIo);
01389 doneSomething=1;
01390 }
01391 }
01392
01393 return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01394 }
01395
01396
01397
01398
01399 int GWEN_Io_LayerHttp_AddRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01400 GWEN_IO_LAYER_HTTP *xio;
01401 GWEN_IO_LAYER_STATUS st;
01402 uint32_t lflags;
01403 uint32_t rflags;
01404
01405 assert(io);
01406 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01407 assert(xio);
01408
01409 st=GWEN_Io_Layer_GetStatus(io);
01410 lflags=GWEN_Io_Layer_GetFlags(io);
01411 rflags=GWEN_Io_Request_GetFlags(r);
01412
01413 switch(GWEN_Io_Request_GetType(r)) {
01414 case GWEN_Io_Request_TypeRead:
01415
01416 if (st!=GWEN_Io_Layer_StatusConnected) {
01417 DBG_INFO(GWEN_LOGDOMAIN, "Layer not connected (%d)", st);
01418 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01419 return GWEN_ERROR_NOT_OPEN;
01420 }
01421
01422 if (xio->lastReadOutResult) {
01423 DBG_INFO(GWEN_LOGDOMAIN, "Unable to read (%d)", xio->lastReadOutResult);
01424 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, xio->lastReadOutResult);
01425 return xio->lastReadOutResult;
01426 }
01427
01428
01429 if (xio->readRequestIn) {
01430 DBG_INFO(GWEN_LOGDOMAIN, "There already is a read request");
01431 return GWEN_ERROR_TRY_AGAIN;
01432 }
01433
01434 if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETBEGIN) {
01435 if (xio->readMode!=GWEN_Io_LayerHttp_Mode_Idle) {
01436 DBG_INFO(GWEN_LOGDOMAIN, "Packetbegin requested while there is still a packet in work");
01437 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01438 return GWEN_ERROR_INVALID;
01439 }
01440
01441 GWEN_Buffer_Reset(xio->readBuffer);
01442 GWEN_DB_ClearGroup(xio->dbCommandIn, NULL);
01443 GWEN_DB_ClearGroup(xio->dbStatusIn, NULL);
01444 GWEN_DB_ClearGroup(xio->dbHeaderIn, NULL);
01445 xio->currentReadChunkSize=-1;
01446 xio->currentReadBodySize=-1;
01447 xio->readLineFinished=0;
01448 if ((lflags & GWEN_IO_LAYER_HTTP_FLAGS_IPC) ||
01449 (lflags & GWEN_IO_LAYER_FLAGS_PASSIVE))
01450 xio->readMode=GWEN_Io_LayerHttp_Mode_Command;
01451 else
01452 xio->readMode=GWEN_Io_LayerHttp_Mode_Status;
01453 }
01454 else {
01455 if (xio->readMode!=GWEN_Io_LayerHttp_Mode_ChunkSize &&
01456 xio->readMode!=GWEN_Io_LayerHttp_Mode_Chunk &&
01457 xio->readMode!=GWEN_Io_LayerHttp_Mode_Body) {
01458 DBG_INFO(GWEN_LOGDOMAIN, "Bad read mode and flag GWEN_IO_REQUEST_FLAGS_PACKETBEGIN not set");
01459 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01460 return GWEN_ERROR_INVALID;
01461 }
01462 }
01463
01464
01465 xio->readRequestIn=r;
01466 GWEN_Io_Request_Attach(xio->readRequestIn);
01467 break;
01468
01469 case GWEN_Io_Request_TypeWrite:
01470
01471 if (st!=GWEN_Io_Layer_StatusConnected) {
01472 DBG_INFO(GWEN_LOGDOMAIN, "Layer is not connected");
01473 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01474 return GWEN_ERROR_NOT_OPEN;
01475 }
01476
01477
01478 if (xio->writeRequestIn) {
01479 DBG_INFO(GWEN_LOGDOMAIN, "There already is a write request");
01480 return GWEN_ERROR_TRY_AGAIN;
01481 }
01482
01483 if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETBEGIN) {
01484 int rv;
01485
01486 if (xio->writeMode!=GWEN_Io_LayerHttp_Mode_Idle && xio->writeMode!=GWEN_Io_LayerHttp_Mode_Finished) {
01487 DBG_INFO(GWEN_LOGDOMAIN, "Packetbegin requested while there is still a packet in work");
01488 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01489 return GWEN_ERROR_INVALID;
01490 }
01491
01492 DBG_VERBOUS(GWEN_LOGDOMAIN, "Packet begin");
01493 GWEN_Buffer_Reset(xio->writeBuffer);
01494
01495 if ((lflags & GWEN_IO_LAYER_HTTP_FLAGS_IPC) ||
01496 !(lflags & GWEN_IO_LAYER_FLAGS_PASSIVE)) {
01497 rv=GWEN_Io_LayerHttp_WriteCommand(io, xio->writeBuffer);
01498 xio->writeMode=GWEN_Io_LayerHttp_Mode_Command;
01499 }
01500 else {
01501 rv=GWEN_Io_LayerHttp_WriteStatus(io, xio->writeBuffer);
01502 xio->writeMode=GWEN_Io_LayerHttp_Mode_Status;
01503 }
01504 if (rv<0) {
01505 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01506 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
01507 xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01508 return rv;
01509 }
01510
01511 if (rflags & GWEN_IO_REQUEST_FLAGS_PACKETEND)
01512
01513 GWEN_DB_SetIntValue(xio->dbHeaderOut, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-length",
01514 GWEN_Io_Request_GetBufferSize(r));
01515
01516
01517 rv=GWEN_Io_LayerHttp_WriteHeader(io, xio->writeBuffer);
01518 if (rv<0) {
01519 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01520 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, rv);
01521 xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01522 return rv;
01523 }
01524 GWEN_Buffer_Rewind(xio->writeBuffer);
01525 xio->writeMode=GWEN_Io_LayerHttp_Mode_Header;
01526 DBG_VERBOUS(GWEN_LOGDOMAIN, "Buffer: %d/%d",
01527 GWEN_Buffer_GetBytesLeft(xio->writeBuffer),
01528 GWEN_Buffer_GetUsedBytes(xio->writeBuffer));
01529 }
01530 else {
01531 if (xio->writeMode!=GWEN_Io_LayerHttp_Mode_Body) {
01532 if ((GWEN_Io_Request_GetBufferSize(r)==0) &&
01533 (rflags & GWEN_IO_REQUEST_FLAGS_FLUSH)) {
01534
01535 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01536 return 0;
01537 }
01538 else {
01539 DBG_INFO(GWEN_LOGDOMAIN, "Bad write mode and flag GWEN_IO_REQUEST_FLAGS_PACKETBEGIN not set");
01540 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_INVALID);
01541 return GWEN_ERROR_INVALID;
01542 }
01543 }
01544 }
01545
01546
01547 xio->writeRequestIn=r;
01548 GWEN_Io_Request_Attach(xio->writeRequestIn);
01549 break;
01550
01551 case GWEN_Io_Request_TypeConnect:
01552
01553 if (st!=GWEN_Io_Layer_StatusUnconnected &&
01554 st!=GWEN_Io_Layer_StatusDisconnected) {
01555 DBG_INFO(GWEN_LOGDOMAIN, "Layer not un-/disconnected");
01556 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01557 return GWEN_ERROR_NOT_OPEN;
01558 }
01559 else {
01560
01561 xio->lastReadOutResult=0;
01562 GWEN_Buffer_Reset(xio->readBuffer);
01563 xio->readMode=GWEN_Io_LayerHttp_Mode_Idle;
01564 xio->currentReadChunkSize=-1;
01565 xio->currentReadBodySize=-1;
01566 xio->readLineFinished=0;
01567
01568 xio->lastWriteOutResult=0;
01569 GWEN_Buffer_Reset(xio->writeBuffer);
01570 xio->writeMode=GWEN_Io_LayerHttp_Mode_Idle;
01571
01572 GWEN_DB_ClearGroup(xio->dbCommandIn, NULL);
01573 GWEN_DB_ClearGroup(xio->dbStatusIn, NULL);
01574 GWEN_DB_ClearGroup(xio->dbHeaderIn, NULL);
01575
01576 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusConnected);
01577 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01578 DBG_INFO(GWEN_LOGDOMAIN, "Layer now connected");
01579 }
01580 break;
01581
01582 case GWEN_Io_Request_TypeDisconnect:
01583
01584 if (st!=GWEN_Io_Layer_StatusConnected) {
01585 DBG_INFO(GWEN_LOGDOMAIN, "IO layer is not open");
01586 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_OPEN);
01587 return GWEN_ERROR_NOT_OPEN;
01588 }
01589 else {
01590
01591 GWEN_Io_LayerHttp_AbortInRequests(io, GWEN_ERROR_ABORTED);
01592 GWEN_Io_LayerHttp_AbortOutRequests(io);
01593
01594
01595 GWEN_Io_Layer_SetStatus(io, GWEN_Io_Layer_StatusDisconnected);
01596 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, 0);
01597 }
01598 break;
01599
01600 default:
01601 DBG_INFO(GWEN_LOGDOMAIN, "This request type is not supported (%d)", GWEN_Io_Request_GetType(r));
01602 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_NOT_SUPPORTED);
01603 return GWEN_ERROR_NOT_SUPPORTED;
01604 }
01605
01606 return 0;
01607 }
01608
01609
01610
01611 int GWEN_Io_LayerHttp_DelRequest(GWEN_IO_LAYER *io, GWEN_IO_REQUEST *r) {
01612 GWEN_IO_LAYER_HTTP *xio;
01613
01614 assert(io);
01615 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01616 assert(xio);
01617
01618 switch(GWEN_Io_Request_GetType(r)) {
01619 case GWEN_Io_Request_TypeRead:
01620 if (xio->readRequestIn==r) {
01621 DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted read request");
01622 xio->readRequestIn=NULL;
01623 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01624 GWEN_Io_Request_free(r);
01625 }
01626 else {
01627
01628 DBG_INFO(GWEN_LOGDOMAIN, "Read request not registered with this io layer");
01629 return GWEN_ERROR_INVALID;
01630 }
01631 break;
01632
01633 case GWEN_Io_Request_TypeWrite:
01634 if (xio->writeRequestIn==r) {
01635 DBG_DEBUG(GWEN_LOGDOMAIN, "Aborted write request");
01636 xio->writeRequestIn=NULL;
01637 GWEN_Io_Request_Finished(r, GWEN_Io_Request_StatusFinished, GWEN_ERROR_ABORTED);
01638 GWEN_Io_Request_free(r);
01639 }
01640 else {
01641
01642 DBG_INFO(GWEN_LOGDOMAIN, "Write request not registered with this io layer");
01643 return GWEN_ERROR_INVALID;
01644 }
01645 break;
01646
01647 default:
01648 break;
01649 }
01650
01651 return 0;
01652 }
01653
01654
01655
01656 int GWEN_Io_LayerHttp_HasWaitingRequests(GWEN_IO_LAYER *io) {
01657 GWEN_IO_LAYER_HTTP *xio;
01658
01659 assert(io);
01660 xio=GWEN_INHERIT_GETDATA(GWEN_IO_LAYER, GWEN_IO_LAYER_HTTP, io);
01661 assert(xio);
01662
01663 if (xio->readRequestIn || xio->writeRequestIn)
01664 return 1;
01665 else
01666 return 0;
01667 }
01668
01669
01670
01671
01672
01673