/** * This function updates all the fields of the current request_t with the new values found in the * request. Since those values will be useful many times, they are strdup-ed in a specific structure * (http_infos_t). Those values *must* be free-ed later on. * * @return 0 if successful, -1 if any error occurs. */ int parse_http_request(request_t *req) { char *ptr, *buf, c; int offset; buf = req->data; /* method */ ptr = strchr(buf, ' '); if (!ptr){ xlog(LOG_ERROR, "%s\n", "Cannot find HTTP method in request"); if (cfg->verbose) xlog(LOG_ERROR, "Buffer sent:\n%s\n", buf); return -1; } c = *ptr; *ptr = '\0'; req->http_infos.method = proxenet_xstrdup2(buf); if (!req->http_infos.method){ xlog(LOG_ERROR, "%s\n", "strdup(method) failed, cannot pursue..."); return -1; } *ptr = c; req->http_infos.proto_type = HTTP; if (!strcmp(req->http_infos.method, "CONNECT")){ /* * We can receive a CONNECT if * - the connection uses HTTPS * - the client tries to upgrade to WebSocket/Secure WebSocket */ char *upgrade_header = get_header_by_name(buf, "Upgrade:"); if (upgrade_header){ if (strcmp(upgrade_header, "WebSocket")==0){ xlog(LOG_INFO, "%s\n", "Upgrading to WebSocket"); req->http_infos.proto_type = WS; req->is_ssl = false; req->http_infos.proto = WS_STRING; req->http_infos.port = HTTP_DEFAULT_PORT; req->http_infos.proto_type = WS; } proxenet_xfree(upgrade_header); } else { req->is_ssl = true; req->http_infos.proto = HTTPS_STRING; req->http_infos.port = HTTPS_DEFAULT_PORT; req->http_infos.proto_type = HTTPS; } offset = ptr - buf + 1; if( get_hostname_from_uri(req, offset) < 0 ){ xlog(LOG_ERROR, "%s\n", "Failed to get hostname (URI)"); goto failed_hostname; } req->http_infos.path = proxenet_xstrdup2("/"); req->http_infos.version = proxenet_xstrdup2("HTTP/1.0"); req->http_infos.uri = get_request_full_uri(req); if(!req->http_infos.uri){ xlog(LOG_ERROR, "%s\n", "get_request_full_uri() failed"); goto failed_uri; } return 0; } /* hostname and port */ if (req->is_ssl){ req->http_infos.port = HTTPS_DEFAULT_PORT; req->http_infos.proto = HTTPS_STRING; } else { req->http_infos.port = HTTP_DEFAULT_PORT; req->http_infos.proto = HTTP_STRING; } if( get_hostname_from_header(req) < 0 ){ xlog(LOG_ERROR, "%s\n", "Failed to get hostname (Host header)"); goto failed_hostname; } /* path */ buf = ptr+1; if (!strncmp(buf, HTTP_PROTO_STRING, strlen(HTTP_PROTO_STRING))){ buf = strchr(buf + 8, '/'); } ptr = strchr(buf, ' '); if (!ptr){ xlog(LOG_ERROR, "%s\n", "Cannot find HTTP path in request"); goto failed_path; } c = *ptr; *ptr = '\0'; req->http_infos.path = proxenet_xstrdup2(buf); if (!req->http_infos.path){ xlog(LOG_ERROR, "%s\n", "strdup(path) failed, cannot pursue..."); goto failed_path; } *ptr = c; buf = ptr+1; /* version */ ptr = strchr(req->data, '\r'); if (!ptr){ xlog(LOG_ERROR, "%s\n", "Cannot find HTTP version"); goto failed_version; } c = *ptr; *ptr = '\0'; req->http_infos.version = proxenet_xstrdup2(buf); if (!req->http_infos.version){ xlog(LOG_ERROR, "%s\n", "strdup(version) failed, cannot pursue..."); goto failed_version; } *ptr = c; /* refresh uri */ req->http_infos.uri = get_request_full_uri(req); if(!req->http_infos.uri){ xlog(LOG_ERROR, "%s\n", "get_request_full_uri() failed"); goto failed_uri; } if (cfg->verbose) { xlog(LOG_INFO, "New request %d to '%s'\n", req->id, req->http_infos.uri); if (cfg->verbose > 1) { xlog(LOG_INFO, "Request HTTP information:\n" "method=%s\n" "proto=%s\n" "hostname=%s\n" "port=%d\n" "path=%s\n" "version=%s\n" , req->http_infos.method, req->http_infos.proto, req->http_infos.hostname, req->http_infos.port, req->http_infos.path, req->http_infos.version); } } return 0; failed_uri: proxenet_xfree(req->http_infos.version); failed_version: proxenet_xfree(req->http_infos.path); failed_path: proxenet_xfree(req->http_infos.hostname); failed_hostname: proxenet_xfree(req->http_infos.method); return -1; }
/** * This function updates all the fields of the current request_t with the new values found in the * request. Since those values will be useful many times, they are strdup-ed in a specific structure * (http_request_t). Those values *must* be free-ed later on. * * @return 0 if successful, -1 if any error occurs. */ int update_http_infos(request_t *req) { char *ptr, *buf, c; buf = req->data; /* method */ ptr = strchr(buf, ' '); if (!ptr){ xlog(LOG_ERROR, "%s\n", "Cannot find HTTP method in request"); if (cfg->verbose) xlog(LOG_ERROR, "Buffer sent:\n%s\n", buf); return -1; } c = *ptr; *ptr = '\0'; req->http_infos.method = proxenet_xstrdup2(buf); if (!req->http_infos.method){ xlog(LOG_ERROR, "%s\n", "strdup(method) failed, cannot pursue..."); return -1; } *ptr = c; if (!strcmp(req->http_infos.method, "CONNECT")){ int offset; req->is_ssl = true; req->http_infos.proto = HTTPS_STRING; req->http_infos.port = HTTPS_DEFAULT_PORT; offset = ptr - buf + 1; if( get_hostname_from_uri(req, offset) < 0 ){ xlog(LOG_ERROR, "%s\n", "Failed to get hostname (URI)"); goto failed_hostname; } req->http_infos.path = proxenet_xstrdup2("/"); req->http_infos.version = proxenet_xstrdup2("HTTP/1.0"); req->http_infos.uri = get_request_full_uri(req); if(!req->http_infos.uri){ xlog(LOG_ERROR, "%s\n", "get_request_full_uri() failed"); goto failed_uri; } return 0; } /* hostname and port */ if (req->is_ssl){ req->http_infos.port = HTTPS_DEFAULT_PORT; req->http_infos.proto = HTTPS_STRING; } else { req->http_infos.port = HTTP_DEFAULT_PORT; req->http_infos.proto = HTTP_STRING; } if( get_hostname_from_header(req) < 0 ){ xlog(LOG_ERROR, "%s\n", "Failed to get hostname (Host header)"); goto failed_hostname; } /* path */ buf = ptr+1; if (!strncmp(buf, HTTP_PROTO_STRING, strlen(HTTP_PROTO_STRING))){ buf = strchr(buf + 8, '/'); } ptr = strchr(buf, ' '); if (!ptr){ xlog(LOG_ERROR, "%s\n", "Cannot find HTTP path in request"); goto failed_path; } c = *ptr; *ptr = '\0'; req->http_infos.path = proxenet_xstrdup2(buf); if (!req->http_infos.path){ xlog(LOG_ERROR, "%s\n", "strdup(path) failed, cannot pursue..."); goto failed_path; } *ptr = c; buf = ptr+1; /* version */ ptr = strchr(req->data, '\r'); if (!ptr){ xlog(LOG_ERROR, "%s\n", "Cannot find HTTP version"); goto failed_version; } c = *ptr; *ptr = '\0'; req->http_infos.version = proxenet_xstrdup2(buf); if (!req->http_infos.version){ xlog(LOG_ERROR, "%s\n", "strdup(version) failed, cannot pursue..."); goto failed_version; } *ptr = c; /* refresh uri */ req->http_infos.uri = get_request_full_uri(req); if(!req->http_infos.uri){ xlog(LOG_ERROR, "%s\n", "get_request_full_uri() failed"); goto failed_uri; } if (cfg->verbose) { xlog(LOG_INFO, "New request %d to '%s'\n", req->id, req->http_infos.uri); if (cfg->verbose >= 2) { xlog(LOG_INFO, "Request HTTP information:\n" "method=%s\n" "proto=%s\n" "hostname=%s\n" "port=%d\n" "path=%s\n" "version=%s\n" , req->http_infos.method, req->http_infos.proto, req->http_infos.hostname, req->http_infos.port, req->http_infos.path, req->http_infos.version); } } return 0; failed_uri: proxenet_xfree(req->http_infos.version); failed_version: proxenet_xfree(req->http_infos.path); failed_path: proxenet_xfree(req->http_infos.hostname); failed_hostname: proxenet_xfree(req->http_infos.method); return -1; }