int call_callback(struct fd_state *state, const char *path, char *sparams, char *scookies) { assert(state && path); struct callback_elem *elem = callback_head; while (elem) { if (strcmp(path, elem->path) == 0) { struct lh_response response; response.header[0] = 0; response.header_len = 0; response.body[0] = 0; response.body_len = 0; struct lh_kv_elem *params = parse_url_params(sparams); struct lh_kv_elem *cookies = parse_cookies(scookies); elem->callback(params, cookies, &response); free_kvs(params); free_kvs(cookies); write_response_header(state, "application/json", response.body_len, response.header); if (response.header_len > 0) write_to_buf(state, response.header, response.header_len); if (response.body_len > 0) write_to_buf(state, response.body, response.body_len); return 1; } elem = elem->next; } return 0; }
int proxyServerLoadRequest(ProxyServer *p, const char *uniqueId, RequestRecord *rec) { reset_request_record(rec); char file_name[512]; struct stat stat_buf; snprintf(file_name, sizeof(file_name), "%s/%s.req", stringAsCString(p->persistenceFolder), uniqueId); rec->fd = open(file_name, O_RDONLY); DIE(p, rec->fd, "Failed to open request file."); int status = fstat(rec->fd, &stat_buf); DIE(p, status, "Failed to get request file size."); rec->map.length = stat_buf.st_size; //Save the size //If file size is 0 then just return if (rec->map.length == 0) { return 0; } rec->map.buffer = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_SHARED, rec->fd, 0); if (rec->map.buffer == MAP_FAILED) { DIE(p, -1, "Failed to map request file."); } //We are good to go. Start parsing. String *str = newString(); int state = PARSE_METHOD; for (size_t i = 0; i < rec->map.length; ++i) { char ch = rec->map.buffer[i]; //printf("[%c %d]", ch, state); if (ch == '\r') { continue; //Ignored } if (state == PARSE_METHOD) { if (ch == ' ') { if (strcmp("CONNECT", stringAsCString(rec->method)) == 0) { state = PARSE_CONNECT_ADDRESS; } else { state = PARSE_PATH; } continue; } stringAppendChar(rec->method, ch); continue; } if (state == PARSE_PATH) { if (ch == '?') { state = PARSE_QUERY_STRING; continue; } if (ch == ' ') { state = PARSE_PROTOCOL_VERSION; continue; } stringAppendChar(rec->path, ch); continue; } if (state == PARSE_QUERY_STRING) { if (ch == ' ') { state = PARSE_PROTOCOL_VERSION; continue; } stringAppendChar(rec->queryString, ch); continue; } if (state == PARSE_PROTOCOL_VERSION) { if (ch == '\n') { state = PARSE_HEADER_NAME; continue; } //Don't store version continue; } if (state == PARSE_CONNECT_ADDRESS) { if (ch == ' ') { state = PARSE_PROTOCOL_VERSION; continue; } //Don't store address continue; } if (state == PARSE_HEADER_NAME) { if (ch == ':') { arrayAdd(rec->headerNames, newStringWithString(str)); str->length = 0; state = PARSE_HEADER_VALUE; continue; } if (ch == '\n') { //End of request headers rec->headerBuffer.buffer = rec->map.buffer; rec->headerBuffer.length = i + 1; rec->bodyBuffer.buffer = rec->map.buffer + i + 1; rec->bodyBuffer.length = rec->map.length - rec->headerBuffer.length; //End parsing for now break; } stringAppendChar(str, ch); continue; } if (state == PARSE_HEADER_VALUE) { if (ch == '\n') { arrayAdd(rec->headerValues, newStringWithString(str)); str->length = 0; state = PARSE_HEADER_NAME; continue; } if ((str->length == 0) && ch == ' ') { //Skip leading space. continue; } stringAppendChar(str, ch); continue; } } deleteString(str); //Parse URL parameters parse_url_params(rec->queryString->buffer, rec->queryString->length, rec->parameterNames, rec->parameterValues); //If form post then parse request body for parameters String *contentType = get_header_value(CONTENT_TYPE, rec); if (contentType != NULL && stringEqualsCString(contentType, FORM_ENC) && rec->bodyBuffer.length > 0) { parse_url_params(rec->bodyBuffer.buffer, rec->bodyBuffer.length, rec->parameterNames, rec->parameterValues); } //It is safe to close the file now. It will //closed anyway by reset method. close(rec->fd); rec->fd = -1; return 0; }