socket.c

来自「Serveez是一个服务器框架」· C语言 代码 · 共 676 行 · 第 1/2 页

C
676
字号
  return sock->check_request (sock);}/* * Allocate a structure of type @code{svz_socket_t} and initialize its data * fields. Assign some of the default callbacks for TCP connections. */svz_socket_t *svz_sock_alloc (void){  svz_socket_t *sock;  char *in;  char *out;  sock = svz_malloc (sizeof (svz_socket_t));  memset (sock, 0, sizeof (svz_socket_t));  in = svz_malloc (RECV_BUF_SIZE);  out = svz_malloc (SEND_BUF_SIZE);  sock->proto = SOCK_FLAG_INIT;  sock->flags = SOCK_FLAG_INIT | SOCK_FLAG_INBUF | SOCK_FLAG_OUTBUF;  sock->userflags = SOCK_FLAG_INIT;  sock->file_desc = -1;  sock->sock_desc = (SOCKET) -1;  sock->pipe_desc[READ] = INVALID_HANDLE;  sock->pipe_desc[WRITE] = INVALID_HANDLE;  sock->read_socket = svz_tcp_read_socket;  sock->write_socket = svz_tcp_write_socket;  sock->check_request = svz_sock_detect_proto;  sock->disconnected_socket = svz_sock_default_disconnect;  sock->recv_buffer = in;  sock->recv_buffer_size = RECV_BUF_SIZE;  sock->send_buffer = out;  sock->send_buffer_size = SEND_BUF_SIZE;  sock->last_send = time (NULL);  sock->last_recv = time (NULL);#if ENABLE_FLOOD_PROTECTION  sock->flood_limit = 100;#endif /* ENABLE_FLOOD_PROTECTION */  return sock;}/* * Resize the send and receive buffers for the socket @var{sock}.  * @var{send_buf_size} is the new size for the send buffer,  * @var{recv_buf_size} for the receive buffer. Note that data may be lost  * when the buffers shrink. */int svz_sock_resize_buffers (svz_socket_t *sock, 			 int send_buf_size, int recv_buf_size){  char *send, *recv;  if (sock->send_buffer_size != send_buf_size)    send = svz_realloc (sock->send_buffer, send_buf_size);  else    send = sock->send_buffer;  if (sock->recv_buffer_size != recv_buf_size)    recv = svz_realloc (sock->recv_buffer, recv_buf_size);  else    recv = sock->recv_buffer;  sock->send_buffer = send;  sock->recv_buffer = recv;  sock->send_buffer_size = send_buf_size;  sock->recv_buffer_size = recv_buf_size;  return 0;}/* * Free the socket structure @var{sock}. Return a non-zero value on error. */intsvz_sock_free (svz_socket_t *sock){  if (sock->recv_buffer)    svz_free (sock->recv_buffer);  if (sock->send_buffer)    svz_free (sock->send_buffer);  if (sock->flags & SOCK_FLAG_LISTENING)    {      if (sock->data)	svz_array_destroy (sock->data);      if (sock->port)	svz_portcfg_destroy (sock->port);    }  if (sock->recv_pipe)    svz_free (sock->recv_pipe);  if (sock->send_pipe)    svz_free (sock->send_pipe);#ifdef __MINGW32__  if (sock->overlap[READ])    svz_free (sock->overlap[READ]);  if (sock->overlap[WRITE])    svz_free (sock->overlap[WRITE]);#endif /* __MINGW32__ */  svz_free (sock);  return 0;}/* * Get local and remote addresses and ports of socket @var{sock} and save  * them into the socket structure. */intsvz_sock_intern_connection_info (svz_socket_t *sock){  struct sockaddr_in s;  socklen_t size = sizeof (s);  unsigned short port;  unsigned long addr;  if (!getpeername (sock->sock_desc, (struct sockaddr *) &s, &size))    {      addr = s.sin_addr.s_addr;      port = s.sin_port;    }  else    {      addr = INADDR_ANY;      port = 0;    }  sock->remote_port = port;  sock->remote_addr = addr;  size = sizeof (s);  if (!getsockname (sock->sock_desc, (struct sockaddr *) &s, &size))    {      addr = s.sin_addr.s_addr;      port = s.sin_port;    }  else    {      addr = INADDR_ANY;      port = 0;    }  sock->local_port = port;  sock->local_addr = addr;  return 0;}/* * Get and clear the pending socket error of a given socket. Print * the result to the log file. */intsvz_sock_error_info (svz_socket_t *sock){  int error;  socklen_t optlen = sizeof (int);  if (getsockopt (sock->sock_desc, SOL_SOCKET, SO_ERROR,                  (void *) &error, &optlen) < 0)    {      svz_log (LOG_ERROR, "getsockopt: %s\n", NET_ERROR);      return -1;    }  if (error)    {#ifdef __MINGW32__      WSASetLastError (error);#else      errno = error;#endif      svz_log (LOG_ERROR, "%s\n", NET_ERROR);      return -1;    }  return 0;}/* * Check if a given socket is still valid. Return non-zero if it is * not. */intsvz_sock_valid (svz_socket_t *sock){  if (!(sock->flags & (SOCK_FLAG_LISTENING | 		       SOCK_FLAG_CONNECTED | SOCK_FLAG_CONNECTING)))    return -1;  if (sock->sock_desc == INVALID_SOCKET)    return -1;  return 0;}/* * Create a socket structure from the file descriptor @var{fd}. Set the  * socket descriptor to non-blocking I/O. Return @code{NULL} on errors. */svz_socket_t *svz_sock_create (int fd){  svz_socket_t *sock;  if (svz_fd_nonblock (fd) != 0)    return NULL;  if (svz_fd_cloexec (fd) != 0)    return NULL;  if ((sock = svz_sock_alloc ()) != NULL)    {      svz_sock_unique_id (sock);      sock->sock_desc = fd;      sock->flags |= (SOCK_FLAG_CONNECTED | SOCK_FLAG_SOCK);      svz_sock_intern_connection_info (sock);    }  return sock;}/* * Disconnect the socket @var{sock} from the network and calls the disconnect  * function for the socket if set. Return a non-zero value on errors. */intsvz_sock_disconnect (svz_socket_t *sock){  /* shutdown client connection */  if (sock->flags & SOCK_FLAG_CONNECTED)    {      if (shutdown (sock->sock_desc, 2) < 0)	svz_log (LOG_ERROR, "shutdown: %s\n", NET_ERROR);      svz_sock_connections--;    }        /* close the server/client socket */  if (closesocket (sock->sock_desc) < 0)    svz_log (LOG_ERROR, "close: %s\n", NET_ERROR);#if ENABLE_DEBUG  svz_log (LOG_DEBUG, "socket %d disconnected\n", sock->sock_desc);#endif  sock->sock_desc = INVALID_SOCKET;  return 0;}/* * Write @var{len} bytes from the memory location pointed to by @var{buf} * to the output buffer of the socket @var{sock}. Also try to flush the  * buffer to the socket of @var{sock} if possible.  Return a non-zero value  * on error, which normally means a buffer overflow. */intsvz_sock_write (svz_socket_t *sock, char *buf, int len){  int ret;  int space;  if (sock->flags & SOCK_FLAG_KILLED)    return 0;  while (len > 0)    {      /* Try to flush the queue of this socket. */      if (sock->write_socket && !sock->unavailable && 	  sock->flags & SOCK_FLAG_CONNECTED && sock->send_buffer_fill)	{	  if ((ret = sock->write_socket (sock)) != 0)	    return ret;	}      if (sock->send_buffer_fill >= sock->send_buffer_size)	{	  /* Queue is full, unlucky socket or pipe ... */	  if (sock->flags & SOCK_FLAG_SEND_PIPE)	    svz_log (LOG_ERROR,		     "send buffer overflow on pipe (%d-%d) (id %d)\n",		     sock->pipe_desc[READ], sock->pipe_desc[WRITE], sock->id);	  else	    svz_log (LOG_ERROR,		     "send buffer overflow on socket %d (id %d)\n",		     sock->sock_desc, sock->id);		  if (sock->kicked_socket)	    sock->kicked_socket (sock, 1);	  return -1;	}          /* Now move as much of BUF into the send queue. */      if (sock->send_buffer_fill + len < sock->send_buffer_size)	{	  memcpy (sock->send_buffer + sock->send_buffer_fill, buf, len);	  sock->send_buffer_fill += len;	  len = 0;	}      else	{	  space = sock->send_buffer_size - sock->send_buffer_fill;	  memcpy (sock->send_buffer + sock->send_buffer_fill, buf, space);	  sock->send_buffer_fill += space;	  len -= space;	  buf += space;	}    }  return 0;}/* * Print a formatted string on the socket @var{sock}. @var{fmt} is the  * printf()-style format string, which describes how to format the optional * arguments. See the printf(3) manual page for details. */intsvz_sock_printf (svz_socket_t *sock, const char *fmt, ...){  va_list args;  static char buffer[VSNPRINTF_BUF_SIZE];  unsigned len;  if (sock->flags & SOCK_FLAG_KILLED)    return 0;  va_start (args, fmt);  len = svz_vsnprintf (buffer, VSNPRINTF_BUF_SIZE, fmt, args);  va_end (args);  /* Just to be sure... */  if (len > sizeof (buffer))    len = sizeof (buffer);  return svz_sock_write (sock, buffer, len);}

⌨️ 快捷键说明

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