int ReadHeaderHeader() { BEGIN("ReadHeaderHeader"); int input; if ((input = mgetv(GBSC_LENGTH)) != GBSC) { if (seof()==0) { WHEREAMI(); printf("Illegal GOB Start Code. Read: %d\n",input); } return(-1); } return(0); }
void process_http(connection *co) { char *data = data = co->buffer.data; int pos, read; if (co->buffer.length == 0 || co->http.ready == 1 || co->http.error == 1) { return; } /* 0 will be erased by the next read()'ing loop */ data[co->buffer.length] = '\0'; data = &data[co->http.pos]; if (*data == '\0') { return; } switch(co->http.step) { case 0: pos = seof(data); if (pos == -1) { return; } if (strncasecmp(data, "POST ", 5) == 0) { co->http.type = HTTP_POST; } else if (strncasecmp(data, "GET ", 4) == 0) { co->http.type = HTTP_GET; } else { /* Other methods are not implemented yet */ co->http.error = 1; return; } co->http.pos = pos; co->http.step = 1; process_http(co); break; case 1: pos = seof(data); if (pos == -1) { return; } if (pos == 1 || (pos == 2 && *data == '\r')) { if (co->http.type == HTTP_GET) { /* Ok, at this point we have a blank line. Ready for GET */ co->http.ready = 1; co->buffer.data[co->http.pos] = '\0'; return; } else { /* Content-Length is mandatory in case of POST */ if (co->http.contentlength == 0) { co->http.error = 1; return; } else { co->http.step = 2; } } } else if (co->http.type == HTTP_POST) { /* looking for content-length instruction */ if (pos <= 25 && strncasecmp("content-length: ", data, 16) == 0) { int cl = atoi(&data[16]); /* Content-length can't be negative... */ if (cl < 1 || cl > MAX_CONTENT_LENGTH) { co->http.error = 1; return; } /* At this time we are ready to read "cl" bytes contents */ co->http.contentlength = cl; } } co->http.pos += pos; process_http(co); break; case 2: read = strlen(data); co->http.pos += read; co->http.read += read; if (co->http.read >= co->http.contentlength) { co->http.ready = 1; /* no more than content-length */ co->buffer.data[co->http.pos - (co->http.read - co->http.contentlength)] = '\0'; } break; default: break; } }
/* Just a lightweight http request processor */ void process_http(ape_socket *co, acetables *g_ape) { ape_buffer *buffer = &co->buffer_in; http_state *http = co->parser.data; ape_parser *parser = &co->parser; char *data = buffer->data; int pos, read, p = 0; if (buffer->length == 0 || parser->ready == 1 || http->error == 1) { return; } /* 0 will be erased by the next read()'ing loop */ data[buffer->length] = '\0'; data = &data[http->pos]; if (*data == '\0') { return; } /* Update the address of http->data and http->uri if buffer->data has changed (realloc) */ if (http->buffer_addr != NULL && buffer->data != http->buffer_addr) { if (http->data != NULL) http->data = &buffer->data[(void *)http->data - (void *)http->buffer_addr]; if (http->uri != NULL) http->uri = &buffer->data[(void *)http->uri - (void *)http->buffer_addr]; http->buffer_addr = buffer->data; } switch(http->step) { case 0: pos = seof(data, '\n'); if (pos == -1) { return; } switch(*(unsigned int *)data) { #ifdef _LITTLE_ENDIAN case 0x20544547: /* GET + space */ #endif #ifdef _BIG_ENDIAN case 0x47455420: /* GET + space */ #endif http->type = HTTP_GET; p = 4; break; #ifdef _LITTLE_ENDIAN case 0x54534F50: /* POST */ #endif #ifdef _BIG_ENDIAN case 0x504F5354: /* POST */ #endif http->type = HTTP_POST; p = 5; break; default: ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid HTTP method in request: %s", data); http->error = 1; shutdown(co->fd, 2); return; } if (data[p] != '/') { http->error = 1; shutdown(co->fd, 2); return; } else { int i = p; while (p++) { switch(data[p]) { case ' ': http->pos = pos; http->step = 1; http->uri = &data[i]; http->buffer_addr = buffer->data; data[p] = '\0'; process_http(co, g_ape); return; case '?': if (data[p+1] != ' ' && data[p+1] != '\r' && data[p+1] != '\n') { http->buffer_addr = buffer->data; http->data = &data[p+1]; } break; case '\r': case '\n': case '\0': ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid line ending in request: %s", data); http->error = 1; shutdown(co->fd, 2); return; } } } break; case 1: pos = seof(data, '\n'); if (pos == -1) { return; } if (pos == 1 || (pos == 2 && *data == '\r')) { if (http->type == HTTP_GET) { /* Ok, at this point we have a blank line. Ready for GET */ buffer->data[http->pos] = '\0'; urldecode(http->uri); parser->onready(parser, g_ape); parser->ready = -1; buffer->length = 0; return; } else if (http->type == HTTP_GET_WS) { /* WebSockets handshake needs to read 8 bytes */ //urldecode(http->uri); http->contentlength = 8; http->buffer_addr = buffer->data; http->data = &buffer->data[http->pos+(pos)]; http->step = 2; } else { /* Content-Length is mandatory in case of POST */ if (http->contentlength == 0) { http->error = 1; shutdown(co->fd, 2); return; } else { http->buffer_addr = buffer->data; // save the addr http->data = &buffer->data[http->pos+(pos)]; http->step = 2; } } } else { struct _http_header_line *hl; if ((hl = parse_header_line(data)) != NULL) { hl->next = http->hlines; http->hlines = hl; if (strcasecmp(hl->key.val, "host") == 0) { http->host = hl->value.val; } } if (http->type == HTTP_POST) { /* looking for content-length instruction */ if (pos <= 25 && strncasecmp("content-length: ", data, 16) == 0) { int cl = atoi(&data[16]); /* Content-length can't be negative... */ if (cl < 1 || cl > MAX_CONTENT_LENGTH) { http->error = 1; shutdown(co->fd, 2); return; } /* At this time we are ready to read "cl" bytes contents */ http->contentlength = cl; } } else if (http->type == HTTP_GET) { if (strncasecmp("Sec-WebSocket-Key1: ", data, 20) == 0) { http->type = HTTP_GET_WS; } } } http->pos += pos; process_http(co, g_ape); break; case 2: read = buffer->length - http->pos; // data length http->pos += read; http->read += read; if (http->read >= http->contentlength) { parser->ready = 1; urldecode(http->uri); /* no more than content-length */ buffer->data[http->pos - (http->read - http->contentlength)] = '\0'; parser->onready(parser, g_ape); parser->ready = -1; buffer->length = 0; } break; default: break; } }
static CONN_STATE process( const POLL_MODE pollMode, const char callGrade ) { KWBoolean master = (KWBoolean) ( pollMode == POLL_ACTIVE ? KWTrue : KWFalse ); KWBoolean aborted = KWFalse; XFER_STATE state = (XFER_STATE) (master ? XFER_SENDINIT : XFER_RECVINIT); XFER_STATE old_state = XFER_EXIT; /* Initialized to any state but the original value of "state" */ XFER_STATE save_state = XFER_EXIT; char currentGrade = (char) ((unsigned char) 0xff); /*--------------------------------------------------------------------*/ /* Yea old state machine for the high level file transfer procotol */ /*--------------------------------------------------------------------*/ while( state != XFER_EXIT ) { printmsg(state == old_state ? 14 : 4 , "process: Machine state is = %c", state ); old_state = state; if ( terminate_processing != aborted ) { aborted = terminate_processing; state = XFER_ABORT; } switch( state ) { case XFER_SENDINIT: /* Initialize outgoing protocol */ state = sinit(); break; case XFER_RECVINIT: /* Initialize Receive protocol */ state = rinit(); break; case XFER_MASTER: /* Begin master mode */ master = KWTrue; state = XFER_NEXTJOB; resetGrade( ); /* Reset best grade status */ currentGrade = E_firstGrade; break; case XFER_SLAVE: /* Begin slave mode */ master = KWFalse; state = XFER_RECVHDR; break; case XFER_NEXTJOB: /* Look for work in local queue */ state = scandir( rmtname, currentGrade ); break; case XFER_REQUEST: /* Process next file in current job in queue */ state = newrequest(); break; case XFER_PUTFILE: /* Got local transmit request */ state = ssfile(); break; case XFER_GETFILE: /* Got local tranmit request */ state = srfile(); break; case XFER_SENDDATA: /* Remote accepted our work, send data */ state = sdata(); break; case XFER_SENDEOF: /* File xfer complete, send EOF */ state = seof( master ); break; case XFER_FILEDONE: /* Receive or transmit is complete */ state = (XFER_STATE) (master ? XFER_REQUEST : XFER_RECVHDR); break; case XFER_NEXTGRADE: /* Process next grade of local files */ currentGrade = nextGrade( callGrade ); if ( currentGrade ) state = XFER_NEXTJOB; else state = XFER_NOLOCAL; break; case XFER_NOLOCAL: /* No local work, remote have any? */ state = sbreak(); break; case XFER_NOREMOTE: /* No remote work, local have any? */ state = schkdir( (KWBoolean) (pollMode == POLL_ACTIVE ? KWTrue : KWFalse ), callGrade ); break; case XFER_RECVHDR: /* Receive header from other host */ state = rheader(); break; case XFER_TAKEFILE: /* Set up to receive remote requested file transfer */ state = rrfile(); break; case XFER_GIVEFILE: /* Set up to transmit remote requuest file transfer */ state = rsfile(); break; case XFER_RECVDATA: /* Receive file data from other host */ state = rdata(); break; case XFER_RECVEOF: state = reof(); break; case XFER_LOST: /* Lost the other host, flame out */ printmsg(0,"process: Connection lost to %s, " "previous system state = %c", rmtname, save_state ); hostp->status.hstatus = HS_CALL_FAILED; state = XFER_EXIT; break; case XFER_ABORT: /* Internal error, flame out */ printmsg(0,"process: Aborting connection to %s, " "previous system state = %c", rmtname, save_state ); hostp->status.hstatus = HS_CALL_FAILED; state = XFER_ENDP; break; case XFER_ENDP: /* Terminate the protocol */ state = endp(); break; default: printmsg(0,"process: Unknown state = %c, " "previous system state = %c", state, save_state ); state = XFER_ABORT; break; } /* switch */ save_state = old_state; /* Used only if we abort */ } /* while( state != XFER_EXIT ) */ /*--------------------------------------------------------------------*/ /* Protocol is complete, terminate the connection */ /*--------------------------------------------------------------------*/ return CONN_TERMINATE; } /* process */