//Returns how much data was removed uint16_t httpd_process_buffer(struct HttpdConnectionSlot *slot) { uint16_t processed = 0, oldprocessed,endline,startline; do { oldprocessed = processed; switch (slot->state) { case HTTPD_STATE_RESPONDING: return 0; //Don't bother doing anything else, buffer now contains an error message, socket should be closed ASAP. case HTTPD_STATE_PARSEVERB: case HTTPD_STATE_PARSEHDRS: for (endline=processed; endline < slot->bufferLen && slot->buffer[endline] != '\n'; endline++); if (endline != slot->bufferLen) { //Remember the line starting point startline = processed; //Mark as processed processed = endline+1; //If the final character is a linefeed, ignore it. if (endline>startline && slot->buffer[endline-1]=='\r') endline--; //Overwrite newline or linefeed with \0 so we can use string functions inside header parsing. slot->buffer[endline]='\0'; //Process verb or header if (slot->state == HTTPD_STATE_PARSEVERB) httpd_process_verb(slot, &slot->buffer[startline], endline-startline); else httpd_process_header(slot, &slot->buffer[startline], endline-startline); } break; case HTTPD_STATE_WAITPOST: //Do we have enough data for the post request? if (slot->bufferLen >= slot->contentLen) { //If so, signal that we are ready to handle this request. slot->state = HTTPD_STATE_READY; } break; } } while (processed != oldprocessed); //Discard all processed data if (processed > 0) { slot->bufferLen -= processed; memcpy(slot->buffer, &slot->buffer[processed], slot->bufferLen); } return processed; }
/** * Read event for EPOLLIN on the httpd protocol module. * * @param dcb The descriptor control block * @return */ static int httpd_read_event(DCB *dcb) { SESSION *session = dcb->session; GWBUF *buf = NULL; char *ptr, *sol; HTTPD_session *client_data = NULL; int n; // Read all the available data if ((n = dcb_read(dcb, &buf)) != -1) { client_data = dcb->data; if (client_data->saved) { buf = gwbuf_append(client_data->saved, buf); client_data->saved = NULL; } buf = gwbuf_make_contiguous(buf); ptr = GWBUF_DATA(buf); if (strncasecmp(ptr, "POST", 4)) { client_data->method = METHOD_POST; gwbuf_add_property(buf, "Method", "POST"); ptr = ptr + 4; } else if (strncasecmp(ptr, "PUT", 3)) { client_data->method = METHOD_PUT; gwbuf_add_property(buf, "Method", "PUT"); ptr = ptr + 3; } else if (strncasecmp(ptr, "GET", 3)) { client_data->method = METHOD_GET; gwbuf_add_property(buf, "Method", "GET"); ptr = ptr + 3; } else if (strncasecmp(ptr, "HEAD", 4)) { client_data->method = METHOD_HEAD; gwbuf_add_property(buf, "Method", "HEAD"); ptr = ptr + 4; } while (ptr < (char *)(buf->end) && isspace(*ptr)) ptr++; sol = ptr; while (ptr < (char *)(buf->end) && isspace(*ptr) == 0) ptr++; client_data->url = strndup(sol, ptr - sol); gwbuf_add_property(buf, "URL", client_data->url); while ((sol = httpd_nextline(buf, ptr)) != NULL && *sol != '\n' && *sol != '\r') { httpd_process_header(buf, sol, client_data); ptr = sol; } /* * We have read all the headers, or run out of data to * examine. */ if (sol == NULL) { client_data->saved = buf; return 0; } else { if (((char *)(buf->end) - sol) < client_data->request_len) { client_data->saved = buf; } else { LOGIF(LT, (skygw_log_write( LOGFILE_TRACE, "HTTPD: request %s.\n", client_data->url))); SESSION_ROUTE_QUERY(session, buf); if (client_data->url) { free(client_data->url); client_data->url = NULL; } } } } return 0; }