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

📄 sockset.c

📁 一个很棒的视频服务器
💻 C
字号:
/*  camserv - An internet streaming picture application * *  Copyright (C) 1999-2002  Jon Travis (jtravis@p00p.org) * *  This program 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 of the License, or *  (at your option) any later version. * *  This program 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 program; if not, write to the Free Software *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <unistd.h>#include <string.h>#include "camserv.h"#include "socket.h"#include "sockset.h"/* * The sockset set provides a lot of convenient, common routines for  * accessing a group of file descriptors.  In a very common select() loop, * the return value from select() in addition to the overhead of managing * all of the descriptor sets can become cumbersome.  These routines allow * the programmer lots of freedom to expand their select() loop without * becoming too bogged down with file descriptor set information. * * The basic loop using the sockset utilities is: * * sockset_reset( socket_set );   // Resets all sockets which are 'active'  * sockset_select( .... );        // Same as a regular select * * set = sockset_query_socks( set ) // Returns set of all clientdatas for *                                  // sockets deemed 'active' by select * ... Manipulate stuff from set ... * free( set ) * * ----------- * * In addition to the basic socket handling procedures, another type * of useful routine is the 'hold' routines.  When a socket should be  * temporarily disabled from being processed by the select() routines,  * it can be put on 'hold'.  Later, all the sockets put on hold can come * off hold, and again be processed by select().   */struct _sockset_st {  fd_set active_fds;              /* FD's passed into and out of select() */  fd_set preserve_fds;            /* FD's copied into active_fds */  int nPreserve_fds;              /* Number of fds in preserve_fds */  int preserve_arr[ FD_SETSIZE ]; /* Array from 0 < nPreserve_fds of each				     fd currently in preserve_fds */  /* Array of managed sockets.  Indexed to match preserve_arr */  const Socket *managed_sockets[ FD_SETSIZE ];   /* Array of clientdatas associated with sockets being managed.       Indexted to match managed_sockets */  const void *managed_cldatas[ FD_SETSIZE ];   /* Information about which file descriptors which are on 'hold' */  struct {    int nHeld;    const Socket *held_sockets[ FD_SETSIZE ];    const void *held_cldatas[ FD_SETSIZE ];  } hold_info;};/* * sockset_new:  Create a new sockset structure, and initialize *               all the values. * * Return values:  Returns NULL on failure, else a valid pointer to *                 freshly malloced memory  */SockSet *sockset_new(){  SockSet *res;  if( (res = malloc( sizeof( *res ))) == NULL )    return NULL;  FD_ZERO( &res->active_fds );  FD_ZERO( &res->preserve_fds );  res->nPreserve_fds = 0;  memset( res->preserve_arr, 0, sizeof( res->preserve_arr ));  memset( res->managed_sockets, 0, sizeof( res->managed_sockets ));  memset( res->managed_cldatas, 0, sizeof( res->managed_cldatas ));  res->hold_info.nHeld = 0;  memset( res->hold_info.held_sockets, 0, sizeof(res->hold_info.held_sockets));  memset( res->hold_info.held_cldatas, 0, sizeof(res->hold_info.held_cldatas));  return res;}/* * sockset_dest:  Destroy a sockset structure * * Arguments:     sset = Sockset structure to destroy */void sockset_dest( SockSet *sset ){  free( sset );}/* * sockset_hold:  Put a given socket on 'hold'  * * Arguments:     sset = Socket set containing the socket *                sock = Socket to be put on hold * * Return values: Returns -1 on failure, 0 on success */int sockset_hold( SockSet *sset, const Socket *sock ){  int i, sfd;  sfd = socket_query_fd( sock );    if( !FD_ISSET( sfd, &sset->preserve_fds ))    return -1;  for( i=0; i< sset->nPreserve_fds; i++ )    if( sset->preserve_arr[ i ] == sfd )      break;  sset->hold_info.held_sockets[ sset->hold_info.nHeld ] =     sset->managed_sockets[ i ];  sset->hold_info.held_cldatas[ sset->hold_info.nHeld ] =     sset->managed_cldatas[ i ];  sset->hold_info.nHeld++;  sockset_del_fd( sset, sock );  return 0;}/* * sockset_unhold_all:   Return all sockets from their 'hold' state *                       to a normal state. * * Arguments:            sset = Socket set to change hold state infos of */void sockset_unhold_all( SockSet *sset ){  int i;  for( i=0; i< sset->hold_info.nHeld; i++ ){    sockset_add_fd( sset, 		    sset->hold_info.held_sockets[ i ],		    sset->hold_info.held_cldatas[ i ] );  }  sset->hold_info.nHeld = 0;}/* * sockset_query_socks:  (accessor function)  Retrieve an array *                       with socket_query_socks( sset ) elements, each *                       pointing to previously given cldata structures *                       which are currently in the active portion of the *                       socket set. * * Arguments:            sset = Sockset as returned from sockset_new() * * Return values:        Returns a malloced chunk of memory containing *                       information provided by the caller (cldata) for each *                       set socket. */void **sockset_query_socks( const SockSet *sset ){  const void **res;  int i, j, nsocks;  if( (nsocks = sockset_query_nsocks( sset )) == 0 )    return NULL;  if( (res = malloc( sizeof( *res ) * nsocks)) == NULL )    return NULL;    for( i=0, j=0; i< sset->nPreserve_fds; i++ ){    if( FD_ISSET( sset->preserve_arr[ i ], &sset->active_fds ) )      res[ j++ ] = sset->managed_cldatas[ i ];  }  return (void **)res;  /* Known cast to eliminate const problems */}/* * sockset_query_nsocks:  Query the number of sockets  in the *                        active set of a sockset * * Arguments:             sset = Sockset as returned from sockset_new() * * Return values:         Returns the # of active sockets. */int sockset_query_nsocks( const SockSet *sset ){  int i, res = 0;  for( i=0; i< sset->nPreserve_fds; i++ )    if( FD_ISSET( sset->preserve_arr[ i ], &sset->active_fds ))      res++;  return res;}/* * sockset_add_sock:  Add a socket to the socket's preserve list *                  * Arguments:         sset = Sockset as returned from sockset_new() *                    socket = Socket to add to the sockset.  Caller must *                             free the socket after sockset destroy. * * Return values:     Returns -1 on failure (too many FDs, or already set), *                    0 on success.a */int sockset_add_fd( SockSet *sset, const Socket *new_sock, const void *cldata){  int new_fd;  new_fd = socket_query_fd( new_sock );    if( sset->nPreserve_fds == FD_SETSIZE )    return -1;    if( FD_ISSET( new_fd, &sset->preserve_fds ) )    return -1;  sset->preserve_arr[ sset->nPreserve_fds ] = new_fd;  sset->managed_sockets[ sset->nPreserve_fds] = new_sock;  sset->managed_cldatas[ sset->nPreserve_fds] = cldata;  sset->nPreserve_fds++;  FD_SET( new_fd, &sset->preserve_fds );  return 0;}/* * sockset_del_fd:  Delete a socket descriptor from the preserve set in a *                  sockset.   * * Arguments:       sset = Sockset as returned from sockset_new() *                  sock = Socket to delete from the sockset.  Caller must *                         free the socket. * * Return values:   Returns -1 if the sock was not contained in the sset, and *                  0 on success */int sockset_del_fd( SockSet *sset, const Socket *sock ){  int i, sfd;  sfd = socket_query_fd( sock );  if( !FD_ISSET( sfd, &sset->preserve_fds ))    return -1;  for( i=0; i< sset->nPreserve_fds; i++ ){    if( sset->preserve_arr[ i ] == sfd )      break;  }  sset->nPreserve_fds--;  memmove( &sset->preserve_arr[ i ],	   &sset->preserve_arr[ i + 1],	   sizeof(sset->preserve_arr[ i ]) * (sset->nPreserve_fds - i ));  memmove( &sset->managed_sockets[ i ],	   &sset->managed_sockets[ i + 1],	   sizeof(sset->managed_sockets[ i ]) * (sset->nPreserve_fds - i ));  memmove( &sset->managed_cldatas[ i ],	   &sset->managed_cldatas[ i + 1],	   sizeof(sset->managed_cldatas[ i ]) * (sset->nPreserve_fds - i ));  FD_CLR( sfd, &sset->preserve_fds );  return 0;}/* * sockset_reset:  Copy the preserve file descriptors to the active *                 file descriptors.  This should be called before *                 any call to sockset_select() * * Arguments:      sset = Sockset as returned from sockset_new() */void sockset_reset( SockSet *sset ){  memcpy( &sset->active_fds, &sset->preserve_fds, sizeof( sset->preserve_fds));}  /* * sockset_select:  Perform a traditional select on socksets.  See select() *                  for more information. * * Arguments:       highest_fd = see select(2) *                  readset    = Set of fd's to check for readability *                  writeset   = Set of fd's to check for writeability *                  tout       = see select(2) * * Return values:   see select(2) */int sockset_select( int highest_fd, 		    SockSet *readset, SockSet *writeset, struct timeval *tout ){  return select( highest_fd, 		 &readset->active_fds,		 &writeset->active_fds,		 NULL,		 tout );}      

⌨️ 快捷键说明

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