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

📄 socket.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 4 页
字号:
  struct sockaddr_in si;  CLEAR (si);  si.sin_addr.s_addr = htonl (addr);  setenv_sockaddr (name_prefix, &si);}/* * Convert protocol names between index and ascii form. */struct proto_names {  const char *short_form;  const char *display_form;};/* Indexed by PROTO_x */static const struct proto_names proto_names[] = {  {"udp",        "UDPv4"},  {"tcp-server", "TCPv4_SERVER"},  {"tcp-client", "TCPv4_CLIENT"}};intascii2proto (const char* proto_name){  int i;  ASSERT (PROTO_N == SIZE (proto_names));  for (i = 0; i < PROTO_N; ++i)    if (!strcmp (proto_name, proto_names[i].short_form))      return i;  return -1;}const char *proto2ascii (int proto, bool display_form){  ASSERT (PROTO_N == SIZE (proto_names));  if (proto < 0 || proto >= PROTO_N)    return "[unknown protocol]";  else if (display_form)    return proto_names[proto].display_form;  else    return proto_names[proto].short_form;}const char *proto2ascii_all (struct gc_arena *gc){  struct buffer out = alloc_buf_gc (256, gc);  int i;  ASSERT (PROTO_N == SIZE (proto_names));  for (i = 0; i < PROTO_N; ++i)    {      if (i)	buf_printf(&out, " ");      buf_printf(&out, "[%s]", proto2ascii(i, false));    }  return BSTR (&out);}/* * Given a local proto, return local proto * if !remote, or compatible remote proto * if remote. * * This is used for options compatibility * checking. */intproto_remote (int proto, bool remote){  ASSERT (proto >= 0 && proto < PROTO_N);  if (remote)    {      if (proto == PROTO_TCPv4_SERVER)	return PROTO_TCPv4_CLIENT;      if (proto == PROTO_TCPv4_CLIENT)	return PROTO_TCPv4_SERVER;    }  return proto;}/* * Bad incoming address lengths that differ from what * we expect are considered to be fatal errors. */voidbad_address_length (int actual, int expected){  msg (M_FATAL, "ERROR: received strange incoming packet with an address length of %d -- we only accept address lengths of %d.",       actual,       expected);}/* * Socket Read Routines */intlink_socket_read_tcp (struct link_socket *sock,		      struct buffer *buf){  int len = 0;  if (!sock->stream_buf.residual_fully_formed)    {#ifdef WIN32      len = socket_finalize (sock->sd, &sock->reads, buf, NULL);#else      struct buffer frag;      stream_buf_get_next (&sock->stream_buf, &frag);      len = recv (sock->sd, BPTR (&frag), BLEN (&frag), MSG_NOSIGNAL);#endif      if (!len)	sock->stream_reset = true;      if (len <= 0)	return buf->len = len;    }  if (sock->stream_buf.residual_fully_formed      || stream_buf_added (&sock->stream_buf, len)) /* packet complete? */    {      stream_buf_get_final (&sock->stream_buf, buf);      stream_buf_reset (&sock->stream_buf);      return buf->len;    }  else    return buf->len = 0; /* no error, but packet is still incomplete */}#ifndef WIN32intlink_socket_read_udp_posix (struct link_socket *sock,			    struct buffer *buf,			    int maxsize,			    struct sockaddr_in *from){  socklen_t fromlen = sizeof (*from);  CLEAR (*from);  ASSERT (buf_safe (buf, maxsize));  buf->len = recvfrom (sock->sd, BPTR (buf), maxsize, 0,		       (struct sockaddr *) from, &fromlen);  if (fromlen != sizeof (*from))    bad_address_length (fromlen, sizeof (*from));  return buf->len;}#endif/* * Socket Write Routines */intlink_socket_write_tcp (struct link_socket *sock,		       struct buffer *buf,		       struct sockaddr_in *to){  packet_size_type len = BLEN (buf);  msg (D_STREAM_DEBUG, "STREAM: WRITE %d offset=%d", (int)len, buf->offset);  ASSERT (len <= sock->stream_buf.maxlen);  len = htonps (len);  ASSERT (buf_write_prepend (buf, &len, sizeof (len)));#ifdef WIN32  return link_socket_write_win32 (sock, buf, to);#else  return link_socket_write_tcp_posix (sock, buf, to);  #endif}/* * Win32 overlapped socket I/O functions. */#ifdef WIN32intsocket_recv_queue (struct link_socket *sock, int maxsize){  if (sock->reads.iostate == IOSTATE_INITIAL)    {      WSABUF wsabuf[1];      int status;      /* reset buf to its initial state */      if (sock->info.proto == PROTO_UDPv4)	{	  sock->reads.buf = sock->reads.buf_init;	}      else if (sock->info.proto == PROTO_TCPv4_CLIENT || sock->info.proto == PROTO_TCPv4_SERVER)	{	  stream_buf_get_next (&sock->stream_buf, &sock->reads.buf);	}      else	{	  ASSERT (0);	}      /* Win32 docs say it's okay to allocate the wsabuf on the stack */      wsabuf[0].buf = BPTR (&sock->reads.buf);      wsabuf[0].len = maxsize ? maxsize : BLEN (&sock->reads.buf);      /* check for buffer overflow */      ASSERT (wsabuf[0].len <= BLEN (&sock->reads.buf));      /* the overlapped read will signal this event on I/O completion */      ASSERT (ResetEvent (sock->reads.overlapped.hEvent));      sock->reads.flags = 0;      if (sock->info.proto == PROTO_UDPv4)	{	  sock->reads.addr_defined = true;	  sock->reads.addrlen = sizeof (sock->reads.addr);	  status = WSARecvFrom(			       sock->sd,			       wsabuf,			       1,			       &sock->reads.size,			       &sock->reads.flags,			       (struct sockaddr *) &sock->reads.addr,			       &sock->reads.addrlen,			       &sock->reads.overlapped,			       NULL);	}      else if (sock->info.proto == PROTO_TCPv4_CLIENT || sock->info.proto == PROTO_TCPv4_SERVER)	{	  sock->reads.addr_defined = false;	  status = WSARecv(			   sock->sd,			   wsabuf,			   1,			   &sock->reads.size,			   &sock->reads.flags,			   &sock->reads.overlapped,			   NULL);	}      else	{	  status = 0;	  ASSERT (0);	}      if (!status) /* operation completed immediately? */	{	  if (sock->reads.addr_defined && sock->reads.addrlen != sizeof (sock->reads.addr))	    bad_address_length (sock->reads.addrlen, sizeof (sock->reads.addr));	  sock->reads.iostate = IOSTATE_IMMEDIATE_RETURN;	  /* since we got an immediate return, we must signal the event object ourselves */	  ASSERT (SetEvent (sock->reads.overlapped.hEvent));	  sock->reads.status = 0;	  msg (D_WIN32_IO, "WIN32 I/O: Socket Receive immediate return [%d,%d]",	       (int) wsabuf[0].len,	       (int) sock->reads.size);	       	}      else	{	  status = WSAGetLastError (); 	  if (status == WSA_IO_PENDING) /* operation queued? */	    {	      sock->reads.iostate = IOSTATE_QUEUED;	      sock->reads.status = status;	      msg (D_WIN32_IO, "WIN32 I/O: Socket Receive queued [%d]",		   (int) wsabuf[0].len);	    }	  else /* error occurred */	    {	      struct gc_arena gc = gc_new ();	      ASSERT (SetEvent (sock->reads.overlapped.hEvent));	      sock->reads.iostate = IOSTATE_IMMEDIATE_RETURN;	      sock->reads.status = status;	      msg (D_WIN32_IO, "WIN32 I/O: Socket Receive error [%d]: %s",		   (int) wsabuf[0].len,		   strerror_win32 (status, &gc));	      gc_free (&gc);	    }	}    }  return sock->reads.iostate;}intsocket_send_queue (struct link_socket *sock, struct buffer *buf, const struct sockaddr_in *to){  if (sock->writes.iostate == IOSTATE_INITIAL)    {      WSABUF wsabuf[1];      int status;       /* make a private copy of buf */      sock->writes.buf = sock->writes.buf_init;      sock->writes.buf.len = 0;      ASSERT (buf_copy (&sock->writes.buf, buf));      /* Win32 docs say it's okay to allocate the wsabuf on the stack */      wsabuf[0].buf = BPTR (&sock->writes.buf);      wsabuf[0].len = BLEN (&sock->writes.buf);      /* the overlapped write will signal this event on I/O completion */      ASSERT (ResetEvent (sock->writes.overlapped.hEvent));      sock->writes.flags = 0;      if (sock->info.proto == PROTO_UDPv4)	{	  /* set destination address for UDP writes */	  sock->writes.addr_defined = true;	  sock->writes.addr = *to;	  sock->writes.addrlen = sizeof (sock->writes.addr);	  status = WSASendTo(			       sock->sd,			       wsabuf,			       1,			       &sock->writes.size,			       sock->writes.flags,			       (struct sockaddr *) &sock->writes.addr,			       sock->writes.addrlen,			       &sock->writes.overlapped,			       NULL);	}      else if (sock->info.proto == PROTO_TCPv4_CLIENT || sock->info.proto == PROTO_TCPv4_SERVER)	{	  /* destination address for TCP writes was established on connection initiation */	  sock->writes.addr_defined = false;	  status = WSASend(			   sock->sd,			   wsabuf,			   1,			   &sock->writes.size,			   sock->writes.flags,			   &sock->writes.overlapped,			   NULL);	}      else 	{	  status = 0;	  ASSERT (0);	}      if (!status) /* operation completed immediately? */	{	  sock->writes.iostate = IOSTATE_IMMEDIATE_RETURN;	  /* since we got an immediate return, we must signal the event object ourselves */	  ASSERT (SetEvent (sock->writes.overlapped.hEvent));	  sock->writes.status = 0;	  msg (D_WIN32_IO, "WIN32 I/O: Socket Send immediate return [%d,%d]",	       (int) wsabuf[0].len,	       (int) sock->writes.size);	       	}      else	{	  status = WSAGetLastError (); 	  if (status == WSA_IO_PENDING) /* operation queued? */	    {	      sock->writes.iostate = IOSTATE_QUEUED;	      sock->writes.status = status;	      msg (D_WIN32_IO, "WIN32 I/O: Socket Send queued [%d]",		   (int) wsabuf[0].len);	    }	  else /* error occurred */	    {	      struct gc_arena gc = gc_new ();	      ASSERT (SetEvent (sock->writes.overlapped.hEvent));	      sock->writes.iostate = IOSTATE_IMMEDIATE_RETURN;	      sock->writes.status = status;	      msg (D_WIN32_IO, "WIN32 I/O: Socket Send error [%d]: %s",		   (int) wsabuf[0].len,		   strerror_win32 (status, &gc));	      gc_free (&gc);	    }	}    }  return sock->writes.iostate;}intsocket_finalize (		 SOCKET s,		 struct overlapped_io *io,		 struct buffer *buf,		 struct sockaddr_in *from){  int ret = -1;  BOOL status;  switch (io->iostate)    {    case IOSTATE_QUEUED:      status = WSAGetOverlappedResult(				      s,				      &io->overlapped,				      &io->size,				      FALSE,				      &io->flags				      );      if (status)	{	  /* successful return for a queued operation */	  if (buf)	    *buf = io->buf;	  ret = io->size;	  io->iostate = IOSTATE_INITIAL;	  ASSERT (ResetEvent (io->overlapped.hEvent));	  msg (D_WIN32_IO, "WIN32 I/O: Socket Completion success [%d]", ret);	}      else	{	  /* error during a queued operation */	  ret = -1;	  if (WSAGetLastError() != WSA_IO_INCOMPLETE)	    {	      /* if no error (i.e. just not finished yet), then DON'T execute this code */	      io->iostate = IOSTATE_INITIAL;	      ASSERT (ResetEvent (io->overlapped.hEvent));	      msg (D_WIN32_IO | M_ERRNO_SOCK, "WIN32 I/O: Socket Completion error");	    }	}      break;    case IOSTATE_IMMEDIATE_RETURN:      io->iostate = IOSTATE_INITIAL;      ASSERT (ResetEvent (io->overlapped.hEvent));      if (io->status)	{	  /* error return for a non-queued operation */	  WSASetLastError (io->status);	  ret = -1;	  msg (D_WIN32_IO | M_ERRNO_SOCK, "WIN32 I/O: Socket Completion non-queued error");	}      else	{	  /* successful return for a non-queued operation */	  if (buf)	    *buf = io->buf;	  ret = io->size;	  msg (D_WIN32_IO, "WIN32 I/O: Socket Completion non-queued success [%d]", ret);	}      break;    case IOSTATE_INITIAL: /* were we called without proper queueing? */      WSASetLastError (WSAEINVAL);      ret = -1;      msg (D_WIN32_IO, "WIN32 I/O: Socket Completion BAD STATE");      break;    default:      ASSERT (0);    }    /* return from address if requested */  if (from)    {      if (ret >= 0 && io->addr_defined)	{	  if (io->addrlen != sizeof (io->addr))	    bad_address_length (io->addrlen, sizeof (io->addr));	  *from = io->addr;	}      else	CLEAR (*from);    }    if (buf)    buf->len = ret;  return ret;}#endif /* WIN32 */

⌨️ 快捷键说明

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