static int Request_is_websocket(Request *req) { bstring upgrade,connection; if(req->ws_flags != 0) { return req->ws_flags == 1; } if (Request_get(req, &WS_SEC_WS_KEY) !=NULL && Request_get(req, &WS_SEC_WS_VER) !=NULL && Request_get(req, &WS_HOST) !=NULL && (upgrade = Request_get(req, &WS_UPGRADE)) != NULL && (connection = Request_get(req, &WS_CONNECTION)) != NULL) { if (BSTR_ERR != binstrcaseless(connection,0,&WS_UPGRADE) && !bstrcmp(upgrade,&WS_WEBSOCKET)) { req->ws_flags =1; return 1; } } req->ws_flags =2; return 0; }
static inline bstring Dir_calculate_response(Request *req, FileRecord *file) { int if_unmodified_since = 0; int if_modified_since = 0; bstring if_match = NULL; bstring if_none_match = NULL; if(file) { if(file->is_dir) return bformat(DIR_REDIRECT_FORMAT, bdata(req->host), bdata(req->uri)); if_match = Request_get(req, &HTTP_IF_MATCH); if(!if_match || biseqcstr(if_match, "*") || bstring_match(if_match, &ETAG_PATTERN)) { if_none_match = Request_get(req, &HTTP_IF_NONE_MATCH); if_unmodified_since = Request_get_date(req, &HTTP_IF_UNMODIFIED_SINCE, RFC_822_TIME); if_modified_since = Request_get_date(req, &HTTP_IF_MODIFIED_SINCE, RFC_822_TIME); debug("TESTING WITH: if_match: %s, if_none_match: %s, if_unmodified_since: %d, if_modified_since: %d", bdata(if_match), bdata(if_none_match), if_unmodified_since, if_modified_since); if(if_unmodified_since) { if(file->sb.st_mtime > if_unmodified_since) { req->status_code = 412; return &HTTP_412; } else if(if_none_match) { return Dir_none_match(req, file, if_modified_since, if_none_match); } else if(if_modified_since) { return Dir_if_modified_since(req, file, if_modified_since); } } else if(if_none_match) { return Dir_none_match(req, file, if_modified_since, if_none_match); } else if(if_modified_since) { return Dir_if_modified_since(req, file, if_modified_since); } else { // they've got nothing, 200 req->status_code = 200; return NULL; } } else { req->status_code = 412; return &HTTP_412; } } else { req->status_code = 404; return &HTTP_404; } req->status_code = 500; return &HTTP_500; }
char *test_Request_create() { int rc = 0; size_t nparsed = 0; bstring fake_sender = bfromcstr("FAKESENDER"); Request_init(); Request *req = Request_create(); mu_assert(req != NULL, "Failed to create parser for request."); FILE *infile = fopen("tests/and_suite/ex_httpd_tst_16", "r"); mu_assert(infile != NULL, "Failed to open test file."); bstring data = bread((bNread)fread, infile); fclose(infile); mu_assert(data != NULL, "Failed to read test file."); mu_assert(blength(data) > 0, "Nothing in that file."); Request_start(req); rc = Request_parse(req, bdata(data), blength(data), &nparsed); mu_assert(rc == 1, "It should parse."); mu_assert(nparsed > 0, "Should have parsed something."); bstring payload = Request_to_payload(req, fake_sender, 0, "", 0,conn, NULL); debug("PAYLOAD IS: %s", bdata(payload)); bdestroy(payload); payload = Request_to_tnetstring(req, fake_sender, 0, "", 0,conn, NULL); debug("TNETSTRING PAYLOAD: '%.*s'", blength(payload), bdata(payload)); mu_assert(Request_get(req, &HTTP_IF_MODIFIED_SINCE) != NULL, "Should have an if-modified-since header."); mu_assert(req->host != NULL, "Should have Host header."); mu_assert(Request_get_date(req, &HTTP_IF_MODIFIED_SINCE, RFC_822_TIME) > 0, "Wrong time from header."); mu_assert(Request_get_date(req, &HTTP_IF_UNMODIFIED_SINCE, RFC_822_TIME) == 0, "Unmodified since should be invalid."); mu_assert(Request_get_date(req, &HTTP_IF_NONE_MATCH, RFC_822_TIME) == 0, "None match shouldn't even be a date."); Request_start(req); Request_destroy(req); // test with null Request_destroy(NULL); bdestroy(payload); bdestroy(fake_sender); bdestroy(data); return NULL; }
static void header_done_cb(void *data, const char *at, size_t length) { (void)at; (void)length; Request *req = (Request *)data; // extract content_len const char *clen = bdata(Request_get(req, &HTTP_CONTENT_LENGTH)); if(clen) req->parser.content_len = atoi(clen); // extract host header req->host = Request_get(req, &HTTP_HOST); int colon = bstrchr(req->host, ':'); if(req->host) { req->host_name = colon > 0 ? bHead(req->host, colon) : bstrcpy(req->host); } }
static inline void check_should_close(Connection *conn, Request *req) { if(req->version && biseqcstr(req->version, "HTTP/1.0")) { debug("HTTP 1.0 request coming in from %s", conn->remote); conn->close = 1; } else { bstring conn_close = Request_get(req, &HTTP_CONNECTION); if(conn_close && biseqcstrcaseless(conn_close, "close")) { conn->close = 1; } else { conn->close = 0; } } }
int Request_get_date(Request *req, bstring field, const char *format) { struct tm tm_val; bstring value = Request_get(req, field); if(value) { memset(&tm_val, 0, sizeof(struct tm)); if(strptime(bdata(value), format, &tm_val) == NULL) { return 0; } else { return (int)mktime(&tm_val); } } else { return 0; } }
char *test_Multiple_Header_Request() { int rc = 0; size_t nparsed = 0; Request_init(); Request *req = Request_create(); mu_assert(req != NULL, "Failed to create parser for request."); FILE *infile = fopen("tests/and_suite/ex_httpd_tst_21", "r"); mu_assert(infile != NULL, "Failed to open test file."); bstring data = bread((bNread)fread, infile); fclose(infile); mu_assert(data != NULL, "Failed to read test file."); mu_assert(blength(data) > 0, "Nothing in that file."); Request_start(req); rc = Request_parse(req, bdata(data), blength(data), &nparsed); mu_assert(rc == 1, "It should parse."); mu_assert(nparsed > 0, "Should have parsed something."); mu_assert(Request_get(req, &COOKIE_HEADER) != NULL, "Should have an cookie header."); bstring payload = Request_to_payload(req, &JSON_METHOD, 0, "", 0,conn, NULL); debug("PAYLOAD IS: %s", bdata(payload)); mu_assert(bstrcmp(payload, &EXPECTED_COOKIE_HEADER) == 0, "Expected header not in correct format."); Request_destroy(req); bdestroy(payload); bdestroy(data); return NULL; }
int bbcp_Protocol::Request(bbcp_Node *Node) { long long totsz=0; int retc, numfiles, texists; int outDir = (bbcp_Config.Options & bbcp_OUTDIR) != 0; bbcp_FileSpec *fp; char buff[1024]; // Establish all connections // if (Node->Start(this, !(bbcp_Config.Options & bbcp_CON2SRC)) || Node->getBuffers(1)) return 2; Local = Node; // Establish the target directory // if ((texists = !bbcp_Config.snkSpec->Stat(0)) && bbcp_Config.snkSpec->Info.Otype == 'd') tdir = bbcp_Config.snkSpec->pathname; else {int plen; if (plen = bbcp_Config.snkSpec->filename - bbcp_Config.snkSpec->pathname) strncpy(buff, bbcp_Config.snkSpec->pathname, plen-1); else {buff[0] = '.'; plen = 2;} tdir = buff; buff[plen-1] = '\0'; } // Generate a target directory ID. This will also uncover a missing directory. // fs_obj = bbcp_Config.snkSpec->FSys(); if (texists && bbcp_Config.snkSpec->Info.Otype == 'd') tdir_id = bbcp_Config.snkSpec->Info.fileid; else {bbcp_FileInfo Tinfo; if (!fs_obj || (!(retc = fs_obj->Stat(tdir, &Tinfo)) && Tinfo.Otype != 'd') && outDir) retc = ENOTDIR; if (retc) {bbcp_Fmsg("Request","Target directory", bbcp_Config.snkSpec->pathname,"not found"); return Request_exit(2); } tdir_id = Tinfo.fileid; } // The first step is to perform an flist to get the list of files // if ((numfiles = Request_flist(totsz)) <= 0) return Request_exit((numfiles < 0 ? 22 : 0)); // If we have a number files, the target had better be a directory // if (numfiles > 1 || outDir) {if (!texists) {bbcp_Fmsg("Request", "Target directory", bbcp_Config.snkSpec->pathname, "not found."); return Request_exit(2); } if (bbcp_Config.snkSpec->Info.Otype != 'd') {bbcp_Fmsg("Request", "Target", bbcp_Config.snkSpec->pathname, "is not a directory."); return Request_exit(20); } bbcp_Config.Options |= bbcp_OUTDIR; } // Make sure we have enough space in the filesystem // DEBUG("Preparing to copy " <<numfiles <<" file(s); bytes=" <<totsz); if (!(bbcp_Config.Options & bbcp_NOSPCHK) && !fs_obj->Enough(totsz, numfiles)) {bbcp_Fmsg("Sink", "Insufficient space to copy all the files from", Remote->NodeName()); return Request_exit(28); } // Create all of the required directories // retc = 0; fp = bbcp_Config.srcPath; while(fp && !(retc = fp->Create_Path())) fp = fp->next; if (retc) return Request_exit(retc); // Get each source file // fp = bbcp_Config.srcSpec; while(fp && !(retc=Request_get(fp)) && !(retc=Local->RecvFile(fp,Remote))) {if (bbcp_Config.Options & bbcp_APPEND) totsz -= fp->targetsz; fp = fp->next; } // Now determine if we need to reset the stat info on any paths we created // if ((fp = bbcp_Config.srcPath)) {if (bbcp_Config.Options & bbcp_PCOPY) {while(fp && fp->setStat()) fp = fp->next;} else if (bbcp_Config.ModeD != bbcp_Config.ModeDC) {while(fp && fp->setMode(bbcp_Config.ModeD)) fp = fp->next;} } // Report back how many files and bytes were received // cout <<"200 End: " <<numfiles <<' ' <<totsz <<endl; // All done // return Request_exit(retc); }
int connection_http_to_handler(Connection *conn) { int content_len = Request_content_length(conn->req); int rc = 0; char *body = NULL; Handler *handler = Request_get_action(conn->req, handler); error_unless(handler, conn, 404, "No action for request: %s", bdata(Request_path(conn->req))); bstring expects = Request_get(conn->req, &HTTP_EXPECT); if (expects != NULL) { if (biseqcstr(expects, "100-continue")) { Response_send_status(conn, &HTTP_100); } else { Response_send_status(conn, &HTTP_417); log_info("Client requested unsupported expectation: %s.", bdata(expects)); goto error; } } // we don't need the header anymore, so commit the buffer and deal with the body check(IOBuf_read_commit(conn->iob, Request_header_length(conn->req)) != -1, "Finaly commit failed streaming the connection to http handlers."); if(is_websocket(conn)) { bstring wsKey = Request_get(conn->req, &WS_SEC_WS_KEY); bstring response= websocket_challenge(wsKey); conn->handler = handler; //Response_send_status(conn,response); bdestroy(conn->req->request_method); conn->req->request_method=bfromcstr("WEBSOCKET_HANDSHAKE"); Connection_send_to_handler(conn, handler, bdata(response), blength(response)); bdestroy(response); bdestroy(conn->req->request_method); conn->req->request_method=bfromcstr("WEBSOCKET"); return REQ_SENT; } if(content_len == 0) { body = ""; rc = Connection_send_to_handler(conn, handler, body, content_len); check_debug(rc == 0, "Failed to deliver to the handler."); } else if(content_len > MAX_CONTENT_LENGTH) { rc = Upload_file(conn, handler, content_len); check(rc == 0, "Failed to upload file."); } else { debug("READ ALL CALLED with content_len: %d, and MAX_CONTENT_LENGTH: %d", content_len, MAX_CONTENT_LENGTH); body = IOBuf_read_all(conn->iob, content_len, CLIENT_READ_RETRIES); check(body != NULL, "Client closed the connection during upload."); rc = Connection_send_to_handler(conn, handler, body, content_len); check_debug(rc == 0, "Failed to deliver to the handler."); } Log_request(conn, 200, content_len); return REQ_SENT; error: return CLOSE; }