void process_request(int fd) { struct http_request_data data = http_parse_request(fd); http_print_request_data(&data); write(fd, "received your message\n", 25); }
int main(int argc, char* argv[]){ struct sockaddr_in server_addr; struct sockaddr_in remote_addr; const int BUFFER_SIZE = 4096; char buf[BUFFER_SIZE]; int SERVER_PORT=10000; int listen_fd = socket(AF_INET, SOCK_STREAM, 0); int reuseaddr = 1; setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(SERVER_PORT); printf("binding on port %d\n", SERVER_PORT); if(bind(listen_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){ printf("Could not bind address\n"); return -1; } if(listen(listen_fd, 1) < 0){ printf("Could not listen on port\n"); return -2; } while(1){ socklen_t sock_len = sizeof(remote_addr); int client_fd = accept(listen_fd, (struct sockaddr*)&remote_addr, &sock_len); int pid; if((pid = fork()) == 0){ close(listen_fd); char client_ip[32]; inet_ntop(AF_INET, (const void *)&remote_addr.sin_addr, client_ip, sizeof(client_ip)); printf("Request from %s[fd:%d]\n", client_ip, client_fd); struct HttpRequest request; http_parse_request(client_fd, &request); http_handle_request(&request); close(client_fd); _exit(0); }else if(pid > 0){ close(client_fd); }else{ printf("could not fork sub process\n"); } } return 0; }
/** * Data has been received on this pcb. * For HTTP 1.0, this should normally only happen once (if the request fits in one packet). */ static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { err_t parsed = ERR_ABRT; struct http_state *hs = arg; LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: pcb=0x%08X pbuf=0x%08X err=%s\n", pcb, p, lwip_strerr(err))); if (p != NULL) { /* Inform TCP that we have taken the data. */ tcp_recved(pcb, p->tot_len); } if (hs == NULL) { /* be robust */ LWIP_DEBUGF(HTTPD_DEBUG, ("Error, http_recv: hs is NULL, abort\n")); http_close_conn(pcb, hs); return ERR_OK; } if ((err != ERR_OK) || (p == NULL)) { /* error or closed by other side */ if (p != NULL) { pbuf_free(p); } http_close_conn(pcb, hs); return ERR_OK; } if (hs->file == NULL) { parsed = http_parse_request(p, hs); } else { LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: already sending data\n")); } pbuf_free(p); if (parsed == ERR_OK) { LWIP_DEBUGF(HTTPD_DEBUG, ("http_recv: data %p len %ld\n", hs->file, hs->left)); http_send_data(pcb, hs); } else if (parsed == ERR_ABRT) { http_close_conn(pcb, hs); return ERR_OK; } return ERR_OK; }
int http_parse(struct request_t *self, char *data, int len) { char *p; /* get request line */ p = http_parse_request(self, data, len); if (p == NULL) { return -1; } len -= p - data; data = p; /* get other headers until end of the request */ while ((len > 0) && !((data[0] == '\n') || (len >= 2 && data[0] == '\r' && data[1] == '\n'))) { p = http_parse_header(self, data, len); if (p == NULL) { return -1; } len -= p - data; data = p; } return 0; }
/* * This is annoying, but the caller needs to know the buffer size of * the request that we are using. In most cases, the passed in buffer * is what we use, so it isn't an issue, but if we malloc our own * buffer (see the HTTP_REQ_PENDING case), then the total buffer size * can grow. Thus the buff_sz argument. */ static struct http_request *connection_handle_request(struct connection *c, char *buff, int amnt, int *buff_sz) { struct http_request *r, *last; *buff_sz = amnt; r = http_new_request(c, buff, amnt); if (NULL == r) return NULL; last = r->prev; /* * If a previous request required more data to parse correctly * (was pending), then we need to combine its buffer with the * current one and try to parse again. */ if (last != r && last->flags & HTTP_REQ_PENDING) { char *new_buff; int new_len; if (last->prev != last && last->prev->flags & HTTP_REQ_PENDING) { http_free_request(r); return NULL; } new_len = amnt + last->req_len; new_buff = malloc(new_len + 1); if (NULL == new_buff) { printc("malloc fail 1\n"); fflush(stdout); http_free_request(r); return NULL; } memcpy(new_buff, last->req, last->req_len); memcpy(new_buff + last->req_len, buff, amnt); buff = new_buff; *buff_sz = amnt = new_len; new_buff[new_len] = '\0'; http_free_request(last); if (r->flags & HTTP_REQ_MALLOC) free(r->req); r->req_len = new_len; r->req = new_buff; r->flags |= HTTP_REQ_MALLOC; } /* * Process the list of requests first, then go through and * actually make the requests. */ if (http_parse_request(r)) { char *save_buff; /* parse error?! Parsing broke somewhere _in_ the * message, so we need to report this as an error */ if (r->req_len != amnt) { /* FIXME: kill connection */ http_free_request(r); return NULL; } assert(r->req_len == amnt && r->req == buff); /* * If we failed because we simply don't have a whole * message (more data is pending), then store it away * appropriately. */ save_buff = malloc(amnt + 1); if (NULL == save_buff) { printc("malloc fail 2\n"); fflush(stdout); /* FIXME: kill connection */ http_free_request(r); return NULL; } memcpy(save_buff, buff, amnt); save_buff[amnt] = '\0'; if (r->flags & HTTP_REQ_MALLOC) free(r->req); r->req = save_buff; r->flags |= (HTTP_REQ_PENDING | HTTP_REQ_MALLOC); } return r; }
/* 函数说明:隧道服务端接收一个隧道连接: 一个隧道连接包含两个TCP连接in_fd(接收数据),out_fd(发送数据); 两个TCP连接如何建立,其流程如此: 在接收TCP连接时,如果还没成功接收到一个TCP连接(in_fd&&out_fd==-1)则测试时间为无穷; 否则只等待10s时间来接收下一个TCP连接; 1、首先接收一个TCP连接: 2、然后解析一个HTTP request,如果method是 -1,转到1 3、如果是post ,put,则将in_fd赋值,转到1; 4、如果是get,则将out_fd赋值,转到1; 5、其他,关闭连接,转到1; */ int tunnel_accept(Tunnel *tunnel) { if(tunnel->in_fd!=INVALID_SOCKET&&tunnel->out_fd!=INVALID_SOCKET) { return 0; } //假如该服务端正在连接中,不接受; /* 循环说明: 终止条件:tunnel->in_fd!=INVALID_SOCKET&&tunnel->out_fd!=INVALID_SOCKET 即已建立起两条TCP连接,一条用于发送、一条用于接收数据! 步骤: 1、accept接收一个tcp连接; 2、从该连接中解析一个http request数据包:http_parse_request; 3、根据request数据包中method做出不同的处理:switch(method): case -1,非法数据包,关闭连接; case POST \PUT : */ while(tunnel->in_fd==INVALID_SOCKET||tunnel->out_fd==INVALID_SOCKET) { struct sockaddr_in addr; Http_request *request; //fd_set fs; int m; //timeval t; int len,n; SOCKET s; /* t.tv_sec=2; t.tv_usec=0; FD_ZERO(&fs); FD_SET(tunnel->server_socket,&fs); n=select(0,&fs,NULL,NULL,((tunnel->in_fd!=INVALID_SOCKET||tunnel->out_fd!=INVALID_SOCKET)?&t:NULL)); if(n==SOCKET_ERROR) { return -1; } else if(n==0)break; */ /* 测试服务器套接字是否有connect请求到来; 如果已经连接上一个TCP连接了,就只等ACCEPT_TIME; 否则则一直等待下去; */ len=sizeof(addr); //printf("进入accept函数\n"); s=accept(tunnel->server_socket,(struct sockaddr *)&addr,&len); //printf("accept 函数!错误码:%d\n",WSAGetLastError()); if(s==INVALID_SOCKET)return -1; m=http_parse_request(s,&request); //从连接套接字s读取http request; //output(request); if(m<=0)return m; if(request->method==-1) { closesocket(s); } else if(request->method==HTTP_POST||request->method==HTTP_PUT) { if(tunnel->in_fd==INVALID_SOCKET) { printf("输入数据TCP连接已经建立,远程主机为:[%s]:[%hu]\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port)); tunnel->in_fd=s; // tunnel->in_total_raw+=m; } else closesocket(s); } /* 客户端是准备传数据过来,即Post和Put操作; 如果服务端输入in_fd已经处于连接状态了,关闭此次TCP连接; 否则将其赋值给in_fd; */ else if(request->method==HTTP_GET) { if(tunnel->out_fd==INVALID_SOCKET) { char str[1024]; tunnel->out_fd=s; sprintf(str,"HTTP/1.1 200 OK\r\n" "Content-Length: %d\r\n" "Connection: close\r\n" "Pragma: no-cache\r\n" "Cache-Control: no-cache, no-store, must-revalidate\r\n" "Expires: 0\r\n" "Content-Type: text/html\r\n" "\r\n",tunnel->content_length+1); if(write_all(tunnel->out_fd,str,strlen(str))<=0) { closesocket(tunnel->out_fd); tunnel->out_fd=INVALID_SOCKET; } else { printf("输出数据TCP连接已经建立,远程主机为:[%s]:[%hu]\n",inet_ntoa(addr.sin_addr),ntohs(addr.sin_port)); tunnel->bytes=0; tunnel->buf_len=0; tunnel->buf_ptr=tunnel->buf; //tunnel->out_total_raw+=strlen(str); } } else closesocket(s); } else closesocket(s); http_destroy_request(request); } if(tunnel->in_fd==INVALID_SOCKET||tunnel->out_fd==INVALID_SOCKET) //隧道连接未能成功建立只建立了一半,断开隧道连接; { if(tunnel->in_fd!=INVALID_SOCKET)closesocket(tunnel->in_fd); tunnel->in_fd=INVALID_SOCKET; tunnel_out_disconnect(tunnel); return -1; } return 0; }
int main(int argc, char *argv[]) { struct sockaddr_in server_addr; struct sockaddr_in remote_addr; struct epoll_event ev, events[MAX_EVENTS]; const int BUFFER_SIZE = 4096; char buf[BUFFER_SIZE]; int SERVER_PORT = 10000; int listen_fd = socket(AF_INET, SOCK_STREAM, 0); int reuseaddr = 1; bzero(&ev, sizeof(ev)); int epoll_fd = epoll_create(500/*deprecated?*/); if (epoll_fd == -1) { printf("could not create epoll descriptor\n"); return -1; } setnonblocking(listen_fd); setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(SERVER_PORT); printf("binding on port %d\n", SERVER_PORT); if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { printf("Could not bind address\n"); return -2; } if (listen(listen_fd, 1) < 0) { printf("Could not listen on port\n"); return -3; } ev.events = EPOLLIN; ev.data.fd = listen_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listen_fd, &ev) == -1) { printf("Could not add listen fd to epoll descriptor\n"); return -4; } while (1) { int nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); if (nfds == -1) { printf("Could not wait epoll events\n"); return -5; } for (int n = 0; n < nfds; n++) { if (events[n].data.fd == listen_fd) { socklen_t sock_len = sizeof(remote_addr); int client_fd = accept(listen_fd, (struct sockaddr *)&remote_addr, &sock_len); if (client_fd == -1) { printf("Could not accept connection request\n"); } //char client_ip[32]; //inet_ntop(AF_INET, (const void *)&remote_addr.sin_addr, client_ip, sizeof(client_ip)); //printf("Request from %s[fd:%d]\n", client_ip, client_fd); buffered_request_init(client_fd); setnonblocking(client_fd); setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr)); ev.events = EPOLLIN | EPOLLOUT | EPOLLET; ev.data.fd = client_fd; if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &ev) == -1) { printf("Could not add new connection request to epoll descriptor\n"); } } else { int client_fd = events[n].data.fd; buffered_request_t *buffered = buffered_request_for_connection(client_fd); static int disable_cork = 0; if (events[n].events & EPOLLHUP) { printf("[%d]Hup Disconnected\n", client_fd); setsockopt(client_fd, SOL_TCP, TCP_CORK, &disable_cork, sizeof(disable_cork)); http_close_connection(buffered); // epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, &ev); continue; } if (events[n].events & EPOLLIN) { int read_count = buffered_request_read_all_available_data(buffered); if(read_count > 0){ //printf("[%d]Received request:\n%s\n", client_fd, &(buffered->readbuf[buffered->readpos])); //TODO: handle request only if already a full request http_request_t request; if(http_parse_request(buffered, &request)< 0){ printf("failed to parse request\n"); } http_handle_request(buffered, &request); }else if(read_count == 0){ http_close_connection(buffered); //epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, &ev); continue; } } if (events[n].events & EPOLLOUT) { if(!buffered_request_has_wroten_all(buffered)){ static int enable_cork = 1; setsockopt(client_fd, SOL_TCP, TCP_CORK, &enable_cork, sizeof(enable_cork)); //printf("[%d]SEND response:\n%s\n", client_fd, &(buffered->writebuf[buffered->writepos])); buffered_request_write_all_available_data(buffered); if(buffered_request_has_wroten_all(buffered)){ setsockopt(client_fd, SOL_TCP, TCP_CORK, &disable_cork, sizeof(disable_cork)); //printf("[%d]Disconnected\n", client_fd); http_close_connection(buffered); //epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, &ev); continue; } } } if (events[n].events & EPOLLERR) { printf("[%d] ERR Disconnected\n", client_fd); setsockopt(client_fd, SOL_TCP, TCP_CORK, &disable_cork, sizeof(disable_cork)); http_close_connection(buffered); //epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_fd, &ev); continue; } } } } return 0; }
static void http_io(IOCHAN i, int event) { struct http_channel *hc = iochan_getdata(i); while (event) { if (event == EVENT_INPUT) { int res, reqlen; struct http_buf *htbuf; htbuf = http_buf_create(hc->http_server); res = recv(iochan_getfd(i), htbuf->buf, HTTP_BUF_SIZE -1, 0); if (res == -1 && errno == EAGAIN) { http_buf_destroy(hc->http_server, htbuf); return; } if (res <= 0) { #if HAVE_SYS_TIME_H if (hc->http_server->record_file) { struct timeval tv; gettimeofday(&tv, 0); fprintf(hc->http_server->record_file, "%lld %lld %lld 0\n", (long long) tv.tv_sec, (long long) tv.tv_usec, (long long) iochan_getfd(i)); } #endif http_buf_destroy(hc->http_server, htbuf); fflush(hc->http_server->record_file); http_channel_destroy(i); return; } htbuf->buf[res] = '\0'; htbuf->len = res; http_buf_enqueue(&hc->iqueue, htbuf); while (1) { if (hc->state == Http_Busy) return; reqlen = request_check(hc->iqueue); if (reqlen <= 2) return; // we have a complete HTTP request nmem_reset(hc->nmem); #if HAVE_SYS_TIME_H if (hc->http_server->record_file) { struct timeval tv; int sz = 0; struct http_buf *hb; for (hb = hc->iqueue; hb; hb = hb->next) sz += hb->len; gettimeofday(&tv, 0); fprintf(hc->http_server->record_file, "%lld %lld %lld %d\n", (long long) tv.tv_sec, (long long) tv.tv_usec, (long long) iochan_getfd(i), sz); for (hb = hc->iqueue; hb; hb = hb->next) fwrite(hb->buf, 1, hb->len, hc->http_server->record_file); } #endif if (!(hc->request = http_parse_request(hc, &hc->iqueue, reqlen))) { yaz_log(YLOG_WARN, "Failed to parse request"); http_error(hc, 400, "Bad Request"); return; } hc->response = 0; yaz_log(YLOG_LOG, "Request: %s %s%s%s", hc->request->method, hc->request->path, *hc->request->search ? "?" : "", hc->request->search); if (hc->request->content_buf) yaz_log(YLOG_LOG, "%s", hc->request->content_buf); if (http_weshouldproxy(hc->request)) http_proxy(hc->request); else { // Execute our business logic! hc->state = Http_Busy; http_command(hc); } } } else if (event == EVENT_OUTPUT) { event = 0; if (hc->oqueue) { struct http_buf *wb = hc->oqueue; int res; res = send(iochan_getfd(hc->iochan), wb->buf + wb->offset, wb->len, 0); if (res <= 0) { yaz_log(YLOG_WARN|YLOG_ERRNO, "write"); http_channel_destroy(i); return; } if (res == wb->len) { hc->oqueue = hc->oqueue->next; http_buf_destroy(hc->http_server, wb); } else { wb->len -= res; wb->offset += res; } if (!hc->oqueue) { if (!hc->keep_alive) { http_channel_destroy(i); return; } else { iochan_clearflag(i, EVENT_OUTPUT); if (hc->iqueue) event = EVENT_INPUT; } } } if (!hc->oqueue && hc->proxy && !hc->proxy->iochan) http_channel_destroy(i); // Server closed; we're done } else { yaz_log(YLOG_WARN, "Unexpected event on connection"); http_channel_destroy(i); event = 0; } } }
static int handle_connection(HTTPContext *c) { int len, ret; switch(c->state) { case HTTPSTATE_WAIT_REQUEST: /* timeout ? */ if ((c->timeout - cur_time) < 0) return -1; if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to read if no events */ if (!(c->poll_entry->revents & POLLIN)) return 0; /* read the data */ read_loop: len = recv(c->fd, c->buffer_ptr, 1, 0); if (len < 0) { if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) return -1; } else if (len == 0) { if(!c->keep_alive)return -1; } else { /* search for end of request. */ uint8_t *ptr; c->buffer_ptr += len; ptr = c->buffer_ptr; if ((ptr >= c->buffer + 2 && !memcmp(ptr-2, "\n\n", 2)) || (ptr >= c->buffer + 4 && !memcmp(ptr-4, "\r\n\r\n", 4))) { /* request found : parse it and reply */ ret = http_parse_request(c); if (ret < 0) return -1; } else if (ptr >= c->buffer_end) { /* request too long: cannot do anything */ return -1; } else goto read_loop; } break; case HTTPSTATE_SEND_HEADER: if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to write if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; len = send(c->fd, c->buffer_ptr, c->buffer_end - c->buffer_ptr, 0); if (len < 0) { if (ff_neterrno() != AVERROR(EAGAIN) && ff_neterrno() != AVERROR(EINTR)) { goto close_conn; } } else { c->buffer_ptr += len; c->data_count += len; if (c->buffer_ptr >= c->buffer_end) { av_freep(&c->pb_buffer); if(c->keep_alive){ memset(c->buffer, 0, c->buffer_size); c->buffer_ptr = c->buffer; c->buffer_end = c->buffer + c->buffer_size - 1; c->timeout = cur_time + HTTP_REQUEST_TIMEOUT; c->state = HTTPSTATE_WAIT_REQUEST; c->hls_idx = -1; http_log("%u alive %s\n", ntohs(c->from_addr.sin_port), c->url); return 0; } /* if error, exit */ if (c->http_error) return -1; /* all the buffer was sent : synchronize to the incoming*/ c->state = HTTPSTATE_SEND_DATA_HEADER; c->buffer_ptr = c->buffer_end = c->buffer; } } break; case HTTPSTATE_SEND_DATA: case HTTPSTATE_SEND_DATA_HEADER: case HTTPSTATE_SEND_DATA_TRAILER: if (c->poll_entry->revents & (POLLERR | POLLHUP)) return -1; /* no need to read if no events */ if (!(c->poll_entry->revents & POLLOUT)) return 0; if (http_send_data(c) < 0) return -1; /* close connection if trailer sent */ if (c->state == HTTPSTATE_SEND_DATA_TRAILER) return -1; break; case HTTPSTATE_RECEIVE_DATA: /* no need to read if no events */ if (c->poll_entry->revents & (POLLERR | POLLHUP)){ HLS *s = NULL; if(c->hls_idx >= 0){ s = &s_hls[c->hls_idx]; s->flag = 2; } wake_others(c, HTTPSTATE_SEND_DATA_TRAILER); return -1; } if (!(c->poll_entry->revents & POLLIN)) return 0; if (http_receive_data(c) < 0) return -1; break; case HTTPSTATE_WAIT_FEED: /* no need to read if no events */ if (c->poll_entry->revents & (POLLIN | POLLERR | POLLHUP)) /*19*/ {printf("line %d: %x:%d\n", __LINE__, c->poll_entry->revents, get_socket_error(c->fd)); return -1;} /* nothing to do, we'll be waken up by incoming feed packets */ break; default: return -1; } return 0; close_conn: av_freep(&c->pb_buffer); return -1; }
/* * Launch a http server that listens on the given port. */ void http_server(uint16_t port, void (*callback)(struct http_user_vars_s *), bool launch) { socket_t s_listen = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (s_listen == INVALID_SOCKET) { error("unable to create a socket for the configuration server"); } struct sockaddr_in6 listen_addr; memset(&listen_addr, 0x0, sizeof(listen_addr)); listen_addr.sin6_family = AF_INET6; listen_addr.sin6_port = htons(port); listen_addr.sin6_addr = in6addr_any; int on = 1; setsockopt(s_listen, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); // For Windows we must explicitly allow IPv4 connections on = 0; if (setsockopt(s_listen, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)) != 0) { warning("unable to allow incoming IPv4 connections to configuration " "server"); } if (bind(s_listen, (const void *)&listen_addr, sizeof(listen_addr)) != 0) { error("unable to create configuation server; failed to bind to " "address localhost:%u", port); } if (listen(s_listen, 1) != 0) { error("unable to create configuation server; failed to listen to " "address localhost:%u", port); } // Launch the UI: if (launch) { launch_ui(port); } // Main server loop: while (true) { struct sockaddr_in6 accept_addr; socklen_t accept_len = sizeof(accept_addr); socket_t s = accept(s_listen, (struct sockaddr *)&accept_addr, &accept_len); if (s == INVALID_SOCKET) { warning("unable to accept incoming connection to configuration " "server localhost:%u", port); close_socket(s); continue; } static const struct in6_addr in6addr_loopbackv4 = {{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 127, 0, 0, 1}}}; if (memcmp(&accept_addr.sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback)) != 0 && memcmp(&accept_addr.sin6_addr, &in6addr_loopbackv4, sizeof(in6addr_loopbackv4) - 3) != 0) { warning("unable to accept incoming connection to configuration " "server localhost:%u from non-local address", port); close_socket(s); continue; } char request[MAX_REQUEST_BUFF_SIZE]; struct http_parser_s parser; http_parser_init(&parser); do { size_t n = recv(s, request, sizeof(request)-1, 0); if (n <= 0) { http_user_vars_free(&parser.request.vars); warning("unable to read request for configuration server " "localhost:%u", port); close_socket(s); break; } request[n] = '\0'; http_parse_request(request, n, &parser); switch (parser.state) { case HTTP_STATE_FINAL: break; case HTTP_STATE_ERROR: http_user_vars_free(&parser.request.vars); warning("unable to parse request to configuration server " "localhost:%u", port); close_socket(s); break; default: continue; } http_callback_func_t generate; if (parser.request.method == HTTP_METHOD_GET && (generate = http_lookup_callback(parser.request.name)) != NULL) { http_buffer_t content = http_buffer_open(); if (generate(content)) { bool success = http_send_response(s, 200, content, &parser.request); if (!success) { http_error(s, 500, &parser.request); } } else { http_error(s, 404, &parser.request); } http_buffer_close(content); } else { callback(&parser.request.vars); http_handle_request(s, &parser.request); } shutdown(s, SHUT_RDWR); http_user_vars_free(&parser.request.vars); close_socket(s); } while (false); } }
/* Extract http_pair_t objects from flow's packet_t chain */ int flow_extract_http(flow_t *f) { /* check if the flow is carrying HTTP again */ if( f->http == FALSE) return 1; /* * Find the actual FIN sequences. */ seq_t *seq = f->order->src; seq_t *src_fin_seq = NULL; seq_t *dst_fin_seq = NULL; int found = 0; while(seq != NULL) { /* Update flow's first byte time. * FBT of flow refers to the payload's FBT. */ if(seq->pkt != NULL && found == 0) { found = 1; f->fb_sec = seq->cap_sec; f->fb_usec = seq->cap_usec; } /*Search the FIN sequence in sequence queue.*/ if(seq->th_flags & TH_FIN == TH_FIN) { src_fin_seq = seq; break; } seq = seq->next; } seq = f->order->dst; while(seq != NULL) { /*Search the FIN sequence in sequence queue.*/ if(seq->th_flags & TH_FIN == TH_FIN) { dst_fin_seq = seq; break; } seq = seq->next; } /* * Set the client and server FIN sequences. */ seq_t *fin_seq = NULL; /* The actual FIN sequence. */ u_int8_t fin_dir = 0; /* fin_dir: * 0: Not set; * 1: src_fin_seq is used; * 2: dst_fin_seq is used; */ if (src_fin_seq != NULL && dst_fin_seq == NULL) { fin_seq = src_fin_seq; fin_dir = 1; } else if (src_fin_seq == NULL && dst_fin_seq != NULL) { fin_seq = dst_fin_seq; fin_dir = 2; } else if (src_fin_seq != NULL && dst_fin_seq != NULL) { fin_seq = src_fin_seq; fin_dir = 1; if(compare_sequence_time(src_fin_seq, dst_fin_seq) == 1) { fin_seq = dst_fin_seq; fin_dir = 2; } } else { fin_seq = NULL; fin_dir = 0; } /* * First step: find requests */ packet_t *pkt; request_t *req; response_t *rsp; int reqn = 0; // Number of requests. int rspn = 0; // Number of responses. http_pair_t *new_http = NULL; seq_t *seq_next = NULL; /* for temp */ seq_t *first_seq = NULL; /* Set seq and seq_next */ seq = f->order->src; if( seq != NULL) { seq_next = seq->next; } else { seq_next = NULL; /* NULL */ } if (fin_seq != NULL && seq != NULL) { /*A FIN packet exists.*/ while(compare_sequence_time(seq, fin_seq) < 0) { pkt = seq->pkt; if(pkt != NULL && pkt->http == HTTP_REQ) { /* When a new HTTP request is found, * create a HTTP pair object, then add the object to * flow's HTTP chain. */ reqn++; /* new HTTP pair object*/ new_http = http_new(); first_seq = seq; new_http->req_fb_sec = seq->cap_sec; new_http->req_fb_usec = seq->cap_usec; new_http->req_lb_sec = seq->cap_sec; new_http->req_lb_usec = seq->cap_usec; /* Add the object to flow's HTTP chain */ flow_add_http(f, new_http); /* new request object */ req = http_request_new(); /* Add the request object to the foregoing HTTP pair object */ http_add_request(new_http, req); /* parse and write values to foregoing request object */ http_parse_request(req, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl); } else { /*Omit the TCP handshake sequences.*/ if(new_http == NULL) { seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; continue; } } if( new_http != NULL ) { if( seq_next == NULL || seq_next == fin_seq || seq_next->pkt != NULL ||\ compare_sequence_time(seq_next, fin_seq) >= 0 ){ //assert(seq->nxt_seq != 0); if( seq->nxt_seq != 0){ new_http->req_total_len = seq->nxt_seq - first_seq->seq; new_http->req_body_len = 0; } /*Update flow's last byte time.*/ if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec)) { f->lb_sec = seq->cap_sec; f->lb_usec = seq->cap_usec; } } else { //assert(seq->seq <= seq_next->seq); } } /* Continue to next sequence.*/ seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; } } else { /* No FIN packet found.*/ while(seq != NULL) { pkt = seq->pkt; if(pkt != NULL && pkt->http == HTTP_REQ) { /* When a new HTTP request is found, * create a HTTP pair object, then add the object to * flow's HTTP chain. */ reqn++; /* new HTTP pair object*/ new_http = http_new(); first_seq = seq; new_http->req_fb_sec = seq->cap_sec; new_http->req_fb_usec = seq->cap_usec; new_http->req_lb_sec = seq->cap_sec; new_http->req_lb_usec = seq->cap_usec; /* Add the object to flow's HTTP chain */ flow_add_http(f, new_http); /* new request object */ req = http_request_new(); /* Add the request object to the foregoing HTTP pair object */ http_add_request(new_http, req); /* parse and write values to foregoing request object */ http_parse_request(req, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl); } else { if(new_http == NULL) { /*Omit the TCP handshake sequences.*/ seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; continue; } } if( new_http != NULL ) { if( seq_next == NULL || seq_next->pkt != NULL ) { //assert(seq->nxt_seq != 0); if( seq->nxt_seq != 0){ new_http->req_total_len = seq->nxt_seq - first_seq->seq; new_http->req_body_len = 0; } /*Update flow's last byte time.*/ if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec)) { f->lb_sec = seq->cap_sec; f->lb_usec = seq->cap_usec; } } else { //assert(seq->seq <= seq_next->seq); } } /*Continue to next sequence.*/ seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; } } /* If no responses found, we treat the flow as invalid and stop parsing */ if(reqn == 0) return 1; /* Second step: find responses */ http_pair_t *tmp = f->http_f; http_pair_t *found_http = NULL; seq = f->order->dst; if( seq != NULL) seq_next = seq->next; else seq_next = NULL; /* NULL */ if(fin_seq != NULL && seq != NULL){ /*There is FIN packet.*/ while(compare_sequence_time(seq, fin_seq) < 0) { pkt = seq->pkt; if ( pkt != NULL && pkt->http == HTTP_RSP) { /* * Similar to the request parsing, a new response is * added to the first pair without response */ rspn++; /* Try to find the first pair without response */ while(tmp != NULL) { if(tmp->response_header == NULL) break; tmp = tmp->next; } if(tmp == NULL) /* no response empty, then return */ return 1; else { /*Found!*/ found_http = tmp; first_seq = seq; found_http->rsp_fb_sec = seq->cap_sec; found_http->rsp_fb_usec = seq->cap_usec; rsp = http_response_new(); http_add_response(found_http, rsp); http_parse_response(rsp, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl); } } else { if(found_http == NULL) { seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; continue; } } if ( found_http != NULL ) { /*first_seq != NULL*/ if( seq_next == NULL || seq_next == fin_seq || seq_next->pkt != NULL ||\ compare_sequence_time(seq_next, fin_seq) >= 0 ) { found_http->rsp_lb_sec = seq->cap_sec; found_http->rsp_lb_usec = seq->cap_usec; //assert( seq->nxt_seq != 0 ); if(seq->nxt_seq != 0){ found_http->rsp_total_len = seq->nxt_seq - first_seq->seq; //printf("%d,%d", found_http->rsp_total_len, found_http->response_header->hdlen); //assert(found_http->rsp_total_len >= found_http->response_header->hdlen); found_http->rsp_body_len = found_http->rsp_total_len - found_http->response_header->hdlen; } /*Update flow's last byte time.*/ if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec)) { f->lb_sec = seq->cap_sec; f->lb_usec = seq->cap_usec; } } else { //assert(seq->seq <= seq_next->seq); } } seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; } } else { /*There is no FIN packet.*/ while(seq != NULL) { pkt = seq->pkt; if ( pkt != NULL && pkt->http == HTTP_RSP ) { /* * Similar to the request parsing, a new response is * added to the first pair without response */ rspn++; /* Try to find the first pair without response */ while(tmp != NULL) { if(tmp->response_header == NULL) break; tmp = tmp->next; } if(tmp == NULL) /* no response empty, then return */ return 1; else { /*Found!*/ found_http = tmp; first_seq = seq; found_http->rsp_fb_sec = seq->cap_sec; found_http->rsp_fb_usec = seq->cap_usec; rsp = http_response_new(); http_add_response(found_http, rsp); http_parse_response(rsp, pkt->tcp_odata, pkt->tcp_odata + pkt->tcp_dl); } } else { if(found_http == NULL) { seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; continue; } } if ( found_http != NULL ) { /*first_seq != NULL*/ if( seq_next == NULL || seq_next->pkt != NULL ) { found_http->rsp_lb_sec = seq->cap_sec; found_http->rsp_lb_usec = seq->cap_usec; //assert( seq->nxt_seq != 0 ); if(seq->nxt_seq != 0){ found_http->rsp_total_len = seq->nxt_seq - first_seq->seq; assert(found_http->rsp_total_len >= found_http->response_header->hdlen); found_http->rsp_body_len = found_http->rsp_total_len - found_http->response_header->hdlen; } /*Update flow's last byte time.*/ if ((seq->cap_sec > f->lb_sec) || (seq->cap_sec == f->lb_sec && seq->cap_usec > f->lb_usec)) { f->lb_sec = seq->cap_sec; f->lb_usec = seq->cap_usec; } } else { //assert(seq->seq <= seq_next->seq); } } seq = seq->next; if(seq != NULL) seq_next = seq->next; else break; } } return 0; }
int main() { int port = 80; int sockfd; char* buffer = malloc(sizeof(char*) * 1024); char* filename = malloc(sizeof(char*) * 255); struct http_request* request = malloc(sizeof(*request)); struct http_response* response = malloc(sizeof(*response)); printf("Creating socket\n"); sockfd = create_socket(port); while(1) { int clientfd; clientfd = accept_client(sockfd); http_read_request(clientfd, &buffer); http_parse_request(request, &buffer); // If / is requested, substitute it for index if(strlen(request->path) == 1) { sprintf(request->path, "index"); } // Make sure path not containing . ends with .html if(strstr(request->path, ".") == NULL) { strcat(request->path, ".html"); } printf("[REQUEST] Method: %s\n", request->method); printf("[REQUEST] Path: %s\n", request->path); // Make sure that requested file exists sprintf(filename, "static/%s", request->path); if(file_exists(filename) == false) { sprintf(filename, "static/404.html"); } memset(buffer, '\0', sizeof(char*) * 255); read_file(filename, &buffer); char* content_type = malloc(sizeof(char*) * 255); http_resolve_content_type(&content_type, filename); printf("[RESPONSE] Content-Type: %s\n", content_type); http_set_response(response, &buffer, content_type, strlen(buffer)); http_respond(clientfd, response); close(clientfd); printf("--------------\n"); } free(response->data); free(response->content_type); free(response); free(request->method); free(request->path); free(request); free(filename); close(sockfd); return 0; }