⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tunnel.c

📁 穿越防火墙技术代码
💻 C
📖 第 1 页 / 共 3 页
字号:
      break;    case TUNNEL_ERROR:      tunnel->buf[len] = 0;      log_error ("tunnel_read: received error: %s", tunnel->buf);      errno = EIO;      return -1;    case TUNNEL_CLOSE:      return 0;    case TUNNEL_DISCONNECT:      tunnel_in_disconnect (tunnel);      if (tunnel_is_client (tunnel)	  && tunnel_in_connect (tunnel) == -1)	return -1;      errno = EAGAIN;      return -1;    default:      log_error ("tunnel_read: protocol error: unknown request 0x%02x", req);      errno = EINVAL;      return -1;    }  errno = EAGAIN;  return -1;}inttunnel_pollin_fd (Tunnel *tunnel){  if (tunnel_is_server (tunnel) &&      (tunnel->in_fd == -1 || tunnel->out_fd == -1))    {      if (tunnel->in_fd == -1)	log_verbose ("tunnel_pollin_fd: in_fd = -1; returning server_socket = %d",		     tunnel->server_socket);      else	log_verbose ("tunnel_pollin_fd: out_fd = -1; returning server_socket = %d",		     tunnel->server_socket);      return tunnel->server_socket;    }  else if (tunnel->in_fd != -1)    return tunnel->in_fd;  else    {      log_error ("tunnel_pollin_fd: returning -1");      return -1;    }}/*If the write connection is up and needs padding to the block lengthspecified in the second argument, send some padding.*/inttunnel_maybe_pad (Tunnel *tunnel, size_t length){  size_t padding;  if (tunnel_is_disconnected (tunnel) ||      tunnel->bytes % length == 0 ||      tunnel->padding_only)    return 0;  padding = length - tunnel->bytes % length;  if (padding > tunnel->content_length - tunnel->bytes)    padding = tunnel->content_length - tunnel->bytes;  return tunnel_padding (tunnel, padding);}#if 0ssize_told_parse_header (int s, int *type){  static const char *end_of_header = "\r\n\r\n";  ssize_t n, len = 0;  char c;  int i;  *type = -1;  n = read_all (s, &c, 1);  if (n != 1)    return -1;  len += n;  if (c == 'P')    *type = TUNNEL_IN;  else if (c == 'G')    *type = TUNNEL_OUT;  else    {      log_error ("parse_header: unknown HTTP request starting with '%c'", c);      errno = EINVAL;      return -1;    }  i = 0;  while (i < 4)    {      n = read_all (s, &c, 1);      if (n != 1 && errno != EAGAIN)	return n;      len += n;      if (c == end_of_header[i])	i++;      else	i = 0;    }  return len;}#endifinttunnel_accept (Tunnel *tunnel){  if (tunnel->in_fd != -1 && tunnel->out_fd != -1)    {      log_debug ("tunnel_accept: tunnel already established");      return 0;    }  while (tunnel->in_fd == -1 || tunnel->out_fd == -1)    {      struct sockaddr_in addr;       Http_request *request;      struct pollfd p;      ssize_t m;      int len;      int n;      int s;      p.fd = tunnel->server_socket;      p.events = POLLIN;      n = poll (&p, 1, (tunnel->in_fd != -1 || tunnel->out_fd != -1 ?			ACCEPT_TIMEOUT * 1000 : -1));      if (n == -1)	{	  log_error ("tunnel_accept: poll error: %s", strerror (errno));	  return -1;	}      else if (n == 0)	{	  log_error ("tunnel_accept: poll timed out");	  errno = ETIMEDOUT;	  break;	}      len = sizeof addr;      s = accept (tunnel->server_socket, (struct sockaddr *)&addr, &len);      if (s == -1)	{	  log_error ("tunnel_accept: accept error: %s", strerror (errno));	  return -1;	}      m = http_parse_request (s, &request);      if (m <= 0)	return m;      if (request->method == -1)	{	  log_error ("tunnel_accept: error parsing header: %s",		     strerror (errno));	  close (s);	}      else if (request->method == HTTP_POST ||	       request->method == HTTP_PUT)	{	  if (tunnel->in_fd == -1)	    {	      tunnel->in_fd = s;#ifdef IO_COUNT_HTTP_HEADER	      tunnel->in_total_raw += m; /* from parse_header() */	      log_annoying ("tunnel_accept: in_total_raw = %u",			    tunnel->in_total_raw);#endif	      fcntl (tunnel->in_fd,		     F_SETFL,		     fcntl (tunnel->in_fd, F_GETFL) | O_NONBLOCK);	      tunnel_in_setsockopts (tunnel->in_fd);	      log_debug ("tunnel_accept: input connected");	    }	  else	    {	      log_error ("rejected tunnel_in: already got a connection");	      close (s);	    }	}      else if (request->method == HTTP_GET)	{	  if (tunnel->out_fd == -1)	    {	      char str[1024];	      tunnel->out_fd = s;	      tunnel_out_setsockopts (tunnel->out_fd);	      sprintf (str,"HTTP/1.1 200 OK\r\n"/* "Date: %s\r\n" *//* "Server: %s\r\n" *//* "Last-Modified: %s\r\n" *//* "ETag: %s\r\n" *//* "Accept-Ranges: %s\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" /* FIXME: "0" is not a legitimate HTTP date. */"Content-Type: text/html\r\n""\r\n",		       /* +1 to allow for TUNNEL_DISCONNECT */		       tunnel->content_length + 1);	      if (write_all (tunnel->out_fd, str, strlen (str)) <= 0)		{		  log_error ("tunnel_accept: couldn't write GET header: %s",			     strerror (errno));		  close (tunnel->out_fd);		  tunnel->out_fd = -1;		}	      else		{		  tunnel->bytes = 0;		  tunnel->buf_len = 0;		  tunnel->buf_ptr = tunnel->buf;#ifdef IO_COUNT_HTTP_HEADER		  tunnel->out_total_raw += strlen (str);		  log_annoying ("tunnel_accept: out_total_raw = %u",				tunnel->out_total_raw);#endif		  log_debug ("tunnel_accept: output connected");		}	    }	  else	    {	      log_error ("tunnel_accept: rejected tunnel_out: "			 "already got a connection");	      close (s);	    }	}      else	{	  log_error ("tunnel_accept: unknown header type");	  log_debug ("tunnel_accept: closing connection");	  close (s);	}      http_destroy_request (request);    }  if (tunnel->in_fd == -1 || tunnel->out_fd == -1)    {      log_error ("tunnel_accept: in_fd = %d, out_fd = %d",		 tunnel->in_fd, tunnel->out_fd);      if (tunnel->in_fd != -1)	close (tunnel->in_fd);      tunnel->in_fd = -1;      log_debug ("tunnel_accept: input disconnected");      tunnel_out_disconnect (tunnel);      return -1;    }  return 0;}Tunnel *tunnel_new_server (int port, size_t content_length){  Tunnel *tunnel;  tunnel = malloc (sizeof (Tunnel));  if (tunnel == NULL)    return NULL;  /* If content_length is 0, a value must be determined automatically. */  /* For now, a default value will do. */  if (content_length == 0)    content_length = DEFAULT_CONTENT_LENGTH;  tunnel->in_fd = -1;  tunnel->out_fd = -1;  tunnel->server_socket = -1;  tunnel->dest.host_name = NULL;  tunnel->dest.host_port = port;  tunnel->buf_ptr = tunnel->buf;  tunnel->buf_len = 0;  /* -1 to allow for TUNNEL_DISCONNECT */  tunnel->content_length = content_length - 1;  tunnel->in_total_raw = 0;  tunnel->in_total_data = 0;  tunnel->out_total_raw = 0;  tunnel->out_total_data = 0;  tunnel->strict_content_length = FALSE;  tunnel->server_socket = server_socket (tunnel->dest.host_port, 1);  if (tunnel->server_socket == -1)    {      log_error ("tunnel_new_server: server_socket (%d) = -1",		 tunnel->dest.host_port);      tunnel_destroy (tunnel);      return NULL;    }  return tunnel;}Tunnel *tunnel_new_client (const char *host, int host_port,		   const char *proxy, int proxy_port,		   size_t content_length){  const char *remote;  int remote_port;  Tunnel *tunnel;  log_verbose ("tunnel_new_client (\"%s\", %d, \"%s\", %d, %d)",	       host, host_port, proxy ? proxy : "(null)", proxy_port, 	       content_length);  tunnel = malloc (sizeof (Tunnel));  if (tunnel == NULL)    {      log_error ("tunnel_new_client: out of memory");      return NULL;    }  tunnel->in_fd = -1;  tunnel->out_fd = -1;  tunnel->server_socket = -1;  tunnel->dest.host_name = host;  tunnel->dest.host_port = host_port;  tunnel->dest.proxy_name = proxy;  tunnel->dest.proxy_port = proxy_port;  tunnel->dest.proxy_authorization = NULL;  tunnel->dest.user_agent = NULL;  /* -1 to allow for TUNNEL_DISCONNECT */  tunnel->content_length = content_length - 1;  tunnel->buf_ptr = tunnel->buf;  tunnel->buf_len = 0;  tunnel->in_total_raw = 0;  tunnel->in_total_data = 0;  tunnel->out_total_raw = 0;  tunnel->out_total_data = 0;  tunnel->strict_content_length = FALSE;  if (tunnel->dest.proxy_name == NULL)    {      remote = tunnel->dest.host_name;      remote_port = tunnel->dest.host_port;    }  else    {      remote = tunnel->dest.proxy_name;      remote_port = tunnel->dest.proxy_port;    }  if (set_address (&tunnel->address, remote, remote_port) == -1)    {      log_error ("tunnel_new_client: set_address: %s", strerror (errno));      free (tunnel);      return NULL;    }  return tunnel;}voidtunnel_destroy (Tunnel *tunnel){  if (tunnel_is_connected (tunnel) || tunnel->in_fd != -1)    tunnel_close (tunnel);  if (tunnel->server_socket != -1)    close (tunnel->server_socket);  free (tunnel);}static inttunnel_opt (Tunnel *tunnel, const char *opt, void *data, int get_flag){  if (strcmp (opt, "strict_content_length") == 0)    {      if (get_flag)	*(int *)data = tunnel->strict_content_length;      else	tunnel->strict_content_length = *(int *)data;    }  else if (strcmp (opt, "keep_alive") == 0)    {      if (get_flag)	*(int *)data = tunnel->keep_alive;      else	tunnel->keep_alive = *(int *)data;    }  else if (strcmp (opt, "max_connection_age") == 0)    {      if (get_flag)	*(int *)data = tunnel->max_connection_age;      else	tunnel->max_connection_age = *(int *)data;    }  else if (strcmp (opt, "proxy_authorization") == 0)    {      if (get_flag)	{	  if (tunnel->dest.proxy_authorization == NULL)	    *(char **)data = NULL;	  else	    *(char **)data = strdup (tunnel->dest.proxy_authorization);	}      else	{	  if (tunnel->dest.proxy_authorization != NULL)	    free ((char *)tunnel->dest.proxy_authorization);	  tunnel->dest.proxy_authorization = strdup ((char *)data);	  if (tunnel->dest.proxy_authorization == NULL)	    return -1;	}    }  else if (strcmp (opt, "user_agent") == 0)    {      if (get_flag)	{	  if (tunnel->dest.user_agent == NULL)	    *(char **)data = NULL;	  else	    *(char **)data = strdup (tunnel->dest.user_agent);	}      else	{	  if (tunnel->dest.user_agent != NULL)	    free ((char *)tunnel->dest.user_agent);	  tunnel->dest.user_agent = strdup ((char *)data);	  if (tunnel->dest.user_agent == NULL)	    return -1;	}    }  else    {      errno = EINVAL;      return -1;    }  return 0;}inttunnel_setopt (Tunnel *tunnel, const char *opt, void *data){  return tunnel_opt (tunnel, opt, data, FALSE);}inttunnel_getopt (Tunnel *tunnel, const char *opt, void *data){  return tunnel_opt (tunnel, opt, data, TRUE);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -