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

📄 socket.c

📁 Serveez是一个服务器框架
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * socket.c - socket management implementation * * Copyright (C) 2000, 2001 Stefan Jahn <stefan@lkcc.org> * Copyright (C) 1999 Martin Grabmueller <mgrabmue@cs.tu-berlin.de> * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. *  * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING.  If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: socket.c,v 1.16 2001/08/13 06:56:43 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#define _GNU_SOURCE#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <signal.h>#include <time.h>#if HAVE_UNISTD_H# include <unistd.h>#endif#if HAVE_SYS_TIME_H# include <sys/time.h>#endif#ifdef __MINGW32__# include <winsock2.h>#endif#ifndef __MINGW32__# include <sys/types.h># include <sys/socket.h># include <netinet/in.h># include <netdb.h>#endif#include "libserveez/snprintf.h"#include "libserveez/alloc.h"#include "libserveez/util.h"#include "libserveez/socket.h"#include "libserveez/core.h"#include "libserveez/pipe-socket.h"#include "libserveez/tcp-socket.h"#include "libserveez/server-core.h"#include "libserveez/server.h"/* * Count the number of currently connected sockets. */int svz_sock_connections = 0;#if ENABLE_FLOOD_PROTECTION/* * This routine can be called if flood protection is wished for * socket readers. Return non-zero if the socket should be kicked * because of flood. */intsvz_sock_flood_protect (svz_socket_t *sock, int num_read){  if (!(sock->flags & SOCK_FLAG_NOFLOOD))    {      /*        * Since the default flood limit is 100 a reader can produce        * 5000 bytes per second before it gets kicked.       */      sock->flood_points += 1 + (num_read / 50);	        if (sock->flood_points > sock->flood_limit)	{	  if (sock->kicked_socket)	    sock->kicked_socket (sock, 0);	  return -1;	}    }  return 0;}#endif /* ENABLE_FLOOD_PROTECTION *//* * The default function which gets called when a client shuts down * its socket. @var{sock} is the socket which was closed. */static intsvz_sock_default_disconnect (svz_socket_t *sock){#if ENABLE_DEBUG  svz_log (LOG_DEBUG, "socket id %d disconnected\n", sock->id);#endif  return 0;}/* * This routine gets called whenever data is read from a client socket * accepted by any connection oriented protocol layer (TCP or PIPE). We * try to detect the data streams protocol here. */intsvz_sock_detect_proto (svz_socket_t *sock){  int n;  svz_server_t *server;  svz_portcfg_t *port;  /* return if there are no servers bound to this socket */  if (sock->data == NULL)    return -1;  /* get port configuration of parent */  port = svz_sock_portcfg (sock);  /* go through each server stored in the data field of this socket */  svz_array_foreach (sock->data, server, n)    {      /* can occur if it is actually a packet oriented server */      if (server->detect_proto == NULL)	{	  svz_log (LOG_ERROR, "%s: no detect-proto routine\n", 		   server->type->prefix);	}      /* call protocol detection routine of the server */      else if (server->detect_proto (server, sock))	{	  sock->idle_func = NULL;	  sock->data = NULL;	  sock->cfg = server->cfg;	  if (!server->connect_socket)	    return -1;	  if (server->connect_socket (server, sock))	    return -1;	  return sock->check_request (sock);	}    }  /*   * Discard this socket if there were not any valid protocol   * detected and its receive buffer fill exceeds a maximum value.   */  if (sock->recv_buffer_fill > port->detection_fill)    {#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "socket id %d detection failed\n", sock->id);#endif      return -1;    }  return 0;}/* * Default idle function. This routine simply checks for "dead"  * (non-receiving) sockets (connection oriented protocols only) and rejects  * them by return a non-zero value. */intsvz_sock_idle_protect (svz_socket_t *sock){  svz_portcfg_t *port = svz_sock_portcfg (sock);  if (time (NULL) - sock->last_recv > port->detection_wait)    {#if ENABLE_DEBUG      svz_log (LOG_DEBUG, "socket id %d detection failed\n", sock->id);#endif      return -1;    }  sock->idle_counter = 1;  return 0;}/* * This @code{check_request()} routine could be used by any protocol to  * detect and finally handle packets depending on a specific packet  * boundary. The appropriate @code{handle_request()} is called for each packet * explicitly with the packet length inclusive the packet boundary. */static intsvz_sock_check_request_array (svz_socket_t *sock){  int len = 0;  char *p, *packet, *end;  packet = p = sock->recv_buffer;  end = p + sock->recv_buffer_fill - sock->boundary_size + 1;  do    {      /* Find packet boundary in the receive buffer. */      while (p < end && memcmp (p, sock->boundary, sock->boundary_size))        p++;      /* Found ? */      if (p < end && !memcmp (p, sock->boundary, sock->boundary_size))        {          p += sock->boundary_size;          len += (p - packet);	  /* Call the handle request callback. */	  if (sock->handle_request)	    {	      if (sock->handle_request (sock, packet, p - packet))		return -1;	    }	  packet = p;        }    }  while (p < end);    /* Shuffle data in the receive buffer around. */  svz_sock_reduce_recv (sock, len);    return 0;}/* * This is just the same routine as above, but optimized for one byte * packet delimiters. */static intsvz_sock_check_request_byte (svz_socket_t *sock){  int len = 0;  char *p, *packet, *end;  packet = p = sock->recv_buffer;  end = p + sock->recv_buffer_fill;  do    {      /* Find packet boundary in the receive buffer. */      while (p < end && *p != *sock->boundary)        p++;      /* Found ? */      if (p < end && *p == *sock->boundary)        {          p++;          len += (p - packet);	  /* Call the handle request callback. */	  if (sock->handle_request)	    {	      if (sock->handle_request (sock, packet, p - packet))		return -1;	    }	  packet = p;        }    }  while (p < end);    /* Shuffle data in the receive buffer around. */  svz_sock_reduce_recv (sock, len);    return 0;}/* * The following routine checks for fixed size packets in the receive queue  * of the socket structure @var{sock} and calls the @code{handle_request()}  * callback if so. It is possible to change the fixed packet size in the * @code{handle_request()} callback dynamically. */static intsvz_sock_check_request_size (svz_socket_t *sock){  int len = 0;  char *p, *packet, *end;  packet = p = sock->recv_buffer;  end = p + sock->recv_buffer_fill;  while (p + sock->boundary_size < end)    {      len += sock->boundary_size;      p += sock->boundary_size;      /* Call the handle request callback. */      if (sock->handle_request)	{	  if (sock->handle_request (sock, packet, sock->boundary_size))	    return -1;	}      packet = p;    }  /* Shuffle data in the receive buffer around. */  svz_sock_reduce_recv (sock, len);    return 0;}/* * This function simply checks for the kind of packet delimiter within the  * given socket structure and and assigns one of the default  * @code{check_request()} routines (one or more byte delimiters or a fixed * size). Afterwards this routine will never ever be called again because  * the callback gets overwritten here. */intsvz_sock_check_request (svz_socket_t *sock){  if (sock->boundary_size <= 0)    {      svz_log (LOG_ERROR, "invalid boundary size: %d\n", sock->boundary_size);      return -1;    }  if (sock->boundary == NULL)    sock->check_request = svz_sock_check_request_size;  else if (sock->boundary_size > 1)    sock->check_request = svz_sock_check_request_array;  else    sock->check_request = svz_sock_check_request_byte;

⌨️ 快捷键说明

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