Example #1
0
static inline ssize_t
http_method (int fd, Http_destination *dest,
	     Http_method method, ssize_t length)
{
  char str[1024]; /* FIXME: possible buffer overflow */
  Http_request *request;
  ssize_t n;

  if (fd == -1)
    {
      log_error ("http_method: fd == -1");
      return -1;
    }

  n = 0;
  if (dest->proxy_name != NULL)
    n = sprintf (str, "http://%s:%d", dest->host_name, dest->host_port);
  sprintf (str + n, "/index.html?crap=%ld", time (NULL));

  request = http_create_request (method, str, 1, 1);
  if (request == NULL)
    return -1;

  sprintf (str, "%s:%d", dest->host_name, dest->host_port);
  http_add_header (&request->header, "Host", str);

  if (length >= 0)
    {
      sprintf (str, "%d", length);
      http_add_header (&request->header, "Content-Length", str);
    }

  http_add_header (&request->header, "Connection", "close");

  if (dest->proxy_authorization)
    {
      http_add_header (&request->header,
		       "Proxy-Authorization",
		       dest->proxy_authorization);
    }

  if (dest->user_agent)
    {
      http_add_header (&request->header,
		       "User-Agent",
		       dest->user_agent);
    }

  n = http_write_request (fd, request);
  http_destroy_request (request);
  return n;
}
/*
函数说明:隧道服务端接收一个隧道连接:
一个隧道连接包含两个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;
}
Example #3
0
ssize_t
http_parse_request (int fd, Http_request **request_)
{
  Http_request *request;
  char *data;
  size_t len;
  ssize_t n;

  *request_ = NULL;

  request = malloc (sizeof (Http_request));
  if (request == NULL)
    {
      log_error ("http_parse_request: out of memory");
      return -1;
    }

  request->method = -1;
  request->uri = NULL;
  request->major_version = -1;
  request->minor_version = -1;
  request->header = NULL;

  n = read_until (fd, ' ', &data);
  if (n <= 0)
    {
      free (request);
      return n;
    }
  request->method = http_string_to_method (data, n - 1);
  if (request->method == -1)
    {
      log_error ("http_parse_request: expected an HTTP method");
      free (data);
      free (request);
      return -1;
    }
  data[n - 1] = 0;
  log_verbose ("http_parse_request: method = \"%s\"", data);
  free (data);
  len = n;

  n = read_until (fd, ' ', &data);
  if (n <= 0)
    {
      free (request);
      return n;
    }
  data[n - 1] = 0;
  request->uri = data;
  len += n;
  log_verbose ("http_parse_request: uri = \"%s\"", request->uri);

  n = read_until (fd, '/', &data);
  if (n <= 0)
    {
      http_destroy_request (request);
      return n;
    }
  else if (n != 5 || memcmp (data, "HTTP", 4) != 0)
    {
      log_error ("http_parse_request: expected \"HTTP\"");
      free (data);
      http_destroy_request (request);
      return -1;
    }
  free (data);
  len = n;

  n = read_until (fd, '.', &data);
  if (n <= 0)
    {
      http_destroy_request (request);
      return n;
    }
  data[n - 1] = 0;
  request->major_version = atoi (data);
  log_verbose ("http_parse_request: major version = %d",
	       request->major_version);
  free (data);
  len += n;

  n = read_until (fd, '\r', &data);
  if (n <= 0)
    {
      http_destroy_request (request);
      return n;
    }
  data[n - 1] = 0;
  request->minor_version = atoi (data);
  log_verbose ("http_parse_request: minor version = %d",
	       request->minor_version);
  free (data);
  len += n;

  n = read_until (fd, '\n', &data);
  if (n <= 0)
    {
      http_destroy_request (request);
      return n;
    }
  free (data);
  if (n != 1)
    {
      log_error ("http_parse_request: invalid line ending");
      http_destroy_request (request);
      return -1;
    }
  len += n;

  n = parse_header (fd, &request->header);
  if (n <= 0)
    {
      http_destroy_request (request);
      return n;
    }
  len += n;

  *request_ = request;
 return len;
}