Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
Arquivo: http.c Projeto: nqv/aranea
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;
}
Exemplo n.º 6
0
/*
函数说明:隧道服务端接收一个隧道连接:
一个隧道连接包含两个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;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
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;
        }
    }
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
0
/*
 * 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);
    }
}
Exemplo n.º 11
0
/* 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;
}
Exemplo n.º 12
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;
}