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(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
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
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
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
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
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
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
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
00573 GWEN_Io_Request_free(xio->readRequestOut);
00574 xio->readRequestOut=NULL;
00575 }
00576 }
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 }
00637 }
00638 }
00639 }
00640 else {
00641 int rv;
00642
00643
00644 doneSomething=1;
00645 xio->readLineFinished=0;
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
00694 GWEN_Buffer_AppendByte(xio->readBuffer, 10);
00695 if ((i-xio->lastHeaderPos)==0) {
00696
00697
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;
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
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 }
00770 }
00771 }
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
00807 assert(0);
00808 break;
00809 }
00810 }
00811 }
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
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
00853 xio->lastReadOutResult=GWEN_Io_Request_GetResultCode(xio->readRequestOut);
00854
00855
00856 GWEN_Io_Request_free(xio->readRequestOut);
00857 xio->readRequestOut=NULL;
00858
00859
00860 bposIn+=bposOut;
00861 GWEN_Io_Request_SetBufferPos(rIn, bposIn);
00862
00863 if (xio->currentReadBodySize!=-1) {
00864 xio->currentReadBodySize-=bposOut;
00865 }
00866
00867 if (xio->readMode==GWEN_Io_LayerHttp_Mode_Chunk) {
00868 xio->currentReadChunkSize-=bposOut;
00869 }
00870
00871 if (xio->currentReadBodySize==0) {
00872
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
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
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
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 }
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
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 }
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 }
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 }
00997 }
00998 }
00999 }
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
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
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 }
01116 }
01117 }
01118 else {
01119
01120 GWEN_Buffer_Reset(xio->writeBuffer);
01121 if (xio->currentWriteBodySize!=0)
01122
01123 xio->writeMode=GWEN_Io_LayerHttp_Mode_Body;
01124 else
01125
01126 xio->writeMode=GWEN_Io_LayerHttp_Mode_Finished;
01127 }
01128 }
01129
01130
01131 return (doneSomething==0)?GWEN_Io_Layer_WorkResultBlocking:GWEN_Io_Layer_WorkResultOk;
01132 }
01133
01134
01135
01136
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
01173 xio->lastWriteOutResult=GWEN_Io_Request_GetResultCode(rOut);
01174
01175
01176 GWEN_Io_Request_free(xio->writeRequestOut);
01177 xio->writeRequestOut=NULL;
01178
01179 if (xio->currentWriteBodySize!=-1)
01180 xio->currentWriteBodySize-=bposOut;
01181
01182
01183 if (xio->currentWriteBodySize==0) {
01184
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
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
01201 if (bposIn>=GWEN_Io_Request_GetBufferSize(rIn) ||
01202 (bposIn && !(flagsIn & GWEN_IO_REQUEST_FLAGS_WRITEALL))) {
01203
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
01234 bpos=GWEN_Io_Request_GetBufferPos(rIn);
01235 len=GWEN_Io_Request_GetBufferSize(rIn)-bpos;
01236 if (xio->currentWriteBodySize!=-1 && len>xio->currentWriteBodySize)
01237
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
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 }
01284 }
01285
01286
01287 }
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
01330 if (GWEN_Io_LayerHttp_WorkOnReadRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01331 doneSomething=1;
01332
01333
01334 if (GWEN_Io_LayerHttp_WorkOnWriteRequest(io)!=GWEN_Io_Layer_WorkResultBlocking)
01335 doneSomething=1;
01336
01337
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
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
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
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
01437 xio->readRequestIn=r;
01438 GWEN_Io_Request_Attach(xio->readRequestIn);
01439 break;
01440
01441 case GWEN_Io_Request_TypeWrite:
01442
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
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
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
01485 GWEN_DB_SetIntValue(xio->dbHeaderOut, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-length",
01486 GWEN_Io_Request_GetBufferSize(r));
01487
01488
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
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
01519 xio->writeRequestIn=r;
01520 GWEN_Io_Request_Attach(xio->writeRequestIn);
01521 break;
01522
01523 case GWEN_Io_Request_TypeConnect:
01524
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
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
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
01563 GWEN_Io_LayerHttp_AbortInRequests(io, GWEN_ERROR_ABORTED);
01564 GWEN_Io_LayerHttp_AbortOutRequests(io);
01565
01566
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
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
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