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

📄 sock.c

📁 ping代码的封装
💻 C
字号:
/** * LIBPING socket library * * Copyright (C) 2000, 2001, 2002 by * Jeffrey Fulmer - <jdfulmer@armstrong.com> * This file is distributed as part of libping * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */#ifdef  HAVE_CONFIG_H# include <config.h>#endif/*HAVE_CONFIG_H*/#include <sock.h>#include <fcntl.h>#ifdef  HAVE_ARPA_INET_H# include <arpa/inet.h>#endif/*HAVE_ARPA_INET_H*/ #ifdef  HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif/*HAVE_SYS_SOCKET_H*/ #ifdef  HAVE_NETINET_IN_H# include <netinet/in.h>#endif/*HAVE_NETINET_IN_H*/ #ifdef  HAVE_NETDB_H# include <netdb.h>#endif/*HAVE_NETDB_H*/#include <setup.h>#include <errno.h>/**  * local prototypes  */int mknblock( int socket, int nonblock );ssize_t socket_write( int sock, const void *vbuf, size_t len );  ssize_t ssl_socket_write( CONN *C, const void *vbuf, size_t len );/** * JOEsocket * returns int, socket handle */intJOEsocket( CONN *C, const char *hn ){  int conn;  int serr;   fd_set rs, ws;  struct timeval timeout;  int res;  int herrno;  int error;  socklen_t          len;  struct linger      ling;  struct sockaddr_in cli;   struct hostent     *hp;  struct hostent     hent; #if defined(_AIX)  char *aixbuf;  int  rc;#endif/*_AIX*/   char buf[1024];   char hbf[9000];   C->sock = -1;#ifdef  HAVE_SSL  C->ssl  = NULL;  C->ctx  = NULL;#endif/*HAVE_SSL*/    if( C->prot == HTTPS ){    #ifdef HAVE_SSL      SSL_load_error_strings();      SSLeay_add_ssl_algorithms();      C->ctx = SSL_CTX_new( SSLv3_client_method());      if( C->ctx == NULL ){ perror( "SSL: ctx is NULL" ); }      /* http://www.openssl.org/support/faq.html#USER1       * Perhaps someday I'll learn to read the FAQ       * first and then code second, but probably not.       * Not all OSes have /dev/urandom, we must seed       * the PRNG       */      memset( buf, 0, sizeof( buf ));      RAND_seed( buf, sizeof( buf ));      C->ssl = SSL_new( C->ctx );      SSL_set_connect_state( C->ssl );    #else      return -1;    #endif /* HAVE_SSL */  }  /* create a socket, return -1 on failure */  if(( C->sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ){    return -1;  } #if defined(__GLIBC__)  /* for systems using GNU libc */  if(( gethostbyname_r( hn, &hent, hbf, sizeof(hbf), &hp, &herrno ) < 0 )){    hp = NULL;  }#elif defined(sun)  /* Solaris 5++ */  hp = gethostbyname_r( hn, &hent, hbf, sizeof(hbf), &herrno );#elif defined(_AIX)  aixbuf = (char*)xmalloc( 9000 );  rc  = gethostbyname_r(hn, (struct hostent *)aixbuf,                       (struct hostent_data *)(aixbuf + sizeof(struct hostent)));  hp = (struct hostent*)aixbuf;#elif ( defined(hpux) || defined(__osf__) )  hp = gethostbyname( hn );  herrno = h_errno;#else  /* simply hoping that gethostbyname is thread-safe */  hp = gethostbyname( hn );  herrno = h_errno;#endif/*OS SPECIFICS*/   if( hp == NULL ) return -1;  bzero( &cli, sizeof( cli ));  bcopy( (char*)hp->h_addr, (char*)&cli.sin_addr, hp->h_length );  cli.sin_family = AF_INET;  cli.sin_port = htons( C->port );  ling.l_onoff  = 1;  ling.l_linger = 0;  if( setsockopt( C->sock, SOL_SOCKET, SO_LINGER, &ling, sizeof( ling )) < 0 ){     return -1;      }  /**   * connect to the host    * evaluate the server response and check for   * readability/writeability of the socket....   */   conn = connect( C->sock, (struct sockaddr *)&cli, sizeof(struct sockaddr_in));  if( conn < 0 ){    JOEclose( C );    return -1;  }  else if( conn == 0 ){    goto FINISH; /* immediate connection */  }  else{    /**      * we have a connection, set the     * socket to non-blocking and test     * its integrity.     */    if(( mknblock( C->sock, TRUE )) < 0 ){      return -1;    }    FD_ZERO(&C->rset);    FD_ZERO(&C->wset);    FD_SET( C->sock, &C->rset );        FD_SET( C->sock, &C->wset );        memset((void *)&timeout, '\0', sizeof( struct timeval ));    /**     * the default timeout is set in init.c, it's     * value can be changed by the user in .siegerc,     * but we'll still use a ternary condition since     * you can't be too safe....     */     timeout.tv_sec  = (C->timeout > 0)?C->timeout:60;    timeout.tv_usec = 0;    if(( res = select( C->sock+1, &C->rset, &C->wset, NULL, &timeout )) < 1 ){      perror( "JOEsocket: connection timed out." );      close( C->sock );      return -1;     }    if( FD_ISSET( C->sock, &C->rset) || FD_ISSET( C->sock, &C->wset )){      len = sizeof(error);      if( getsockopt( C->sock, SOL_SOCKET, SO_ERROR, &error, &len ) < 0 )        return(-1);     }  } /* end of connect conditional */FINISH:  /**   * make the socket blocking again.   */  if(( mknblock( C->sock, FALSE )) < 0 ){    perror( "JOEsocket: unable to set socket to non-blocking." );    return -1;  }    /* if requested, encrypt the transaction  */  if( C->prot == HTTPS ){    #ifdef HAVE_SSL      /* currently a fatal error, should it be? */      if(( SSL_set_fd( C->ssl, C->sock )) < 0 ){        perror( "unable to create secure socket!" );        exit( 0 );      }      if(( serr = SSL_connect( C->ssl )) < 0 ){        int problem = SSL_get_error( C->ssl, serr );        fprintf( stderr, "SSL_connect: want to %s more...\n",               ( problem == SSL_ERROR_WANT_READ) ? "read" : "write");        return -1;      }      SSL_get_cipher( C->ssl );    #else      return -1;    #endif /* HAVE_SSL */  }    return((C->sock>0)?C->sock:-1);}/** * makes the socket non-blocking, * calls select with timeout and * returns the socket to blocking. */intJOEsocket_check( CONN *C, SDSET test ){  int res;  struct timeval timeout;   FD_ZERO(&C->rset);  FD_ZERO(&C->wset);  FD_SET( C->sock, &C->rset );  FD_SET( C->sock, &C->wset );  memset((void *)&timeout, '\0', sizeof( struct timeval ));  if(( mknblock( C->sock, TRUE )) < 0 ){    perror( "SIMBOTsocket: unable to set socket to non-blocking." );    return -1;  }   timeout.tv_sec  = ( C->timeout > 0)?C->timeout:60;  timeout.tv_usec = 0;   switch( test ){  case READ:    if(( res = select( C->sock+1, &C->rset, NULL, NULL, &timeout )) < 1 ){      close( C->sock );      return -1;    }    break;  case WRITE:    if(( res = select( C->sock+1, NULL, &C->wset, NULL, &timeout )) < 1 ){      close( C->sock );      return -1;    }    break;  case RDWR:    if(( res = select( C->sock+1, &C->rset, &C->wset, NULL, &timeout )) < 1 ){      close( C->sock );      return -1;    }    break;  }   if(( mknblock( C->sock, FALSE )) < 0 ){    perror( "SIMBOTsocket: unable to set socket to non-blocking." );    return -1;  }  FD_CLR( C->sock, &C->rset );   return 0;}/** * local function * set socket to non-blocking */intmknblock( int sock, int nonblock ){#if HAVE_FCNTL_H   int flags;  int retval;  flags = fcntl( sock, F_GETFL, 0 );  if( flags < 0 ){    perror("fcntl");    return -1;  }  if( nonblock ){     flags |=  O_NDELAY;  }  else{    flags &= ~O_NDELAY;  }  retval = fcntl( sock, F_SETFL, flags);  if( retval < 0 ){    perror("fcntl");    return -1;  } #elif defined( FIONBIO )  ioctl_t status;   status = nb ? 1 : 0;  return ioctl( sd, FIONBIO, &status );#endif}  /** * local function * returns ssize_t * writes vbuf to sock */ssize_tsocket_write( int sock, const void *vbuf, size_t len ){  size_t      n;  ssize_t     w;  const char *buf;   buf = vbuf;  n   = len;  while( n > 0 ){    if(( w = write( sock, buf, n )) <= 0 ){      if( errno == EINTR )        w = 0;      else        return( -1 );    }    n    -= w;    buf += n;  }  return( len );}/** * local function * returns ssize_t * writes vbuf to sock */ssize_tssl_socket_write( CONN *C, const void *vbuf, size_t len ){  size_t      n;  ssize_t     w;  const char *buf;#ifdef HAVE_SSL  buf = vbuf;  n   = len;  while( n > 0 ){    if(( w = SSL_write( C->ssl, buf, n )) <= 0 ){      if( errno == EINTR )        w = 0;      else        return( -1 );    }    n    -= w;    buf += n;  }  return( len );#else  perror( "protocol not supported" );  return -1;#endif/*HAVE_SSL*/}ssize_tJOEreadline( CONN *C, char *ptr, size_t len ){  int n;   do{    n = read( C->sock, ptr, 1 );  } while( n > 0 && *ptr++ != '\n' );   *ptr++=0;  return( n > 0 );} ssize_tJOEsocket_read( CONN *C, void *vbuf, size_t len ){  int type;  size_t      n;  ssize_t     r;  char *buf;    buf = vbuf;  n   = len;    if( C->prot == HTTPS ){  #ifdef HAVE_SSL    while( n > 0 ){       if(( r = SSL_read( C->ssl, buf, n )) < 0 ){        if( errno == EINTR )          r = 0;        else          return( -1 );      }      else if( r == 0 ) break;       n   -= r;      buf += r;    }   /* end of while    */  #endif/*HAVE_SSL*/  }    else{    while( n > 0 ){      if(( r = read( C->sock, buf, n )) < 0 ){        if( errno == EINTR )          r = 0;        else          return( -1 );      }      else if( r == 0 ) break;      n   -= r;      buf += r;    } /* end of while */   }   /* end of else  */  return( len - n );  }  /** * returns void * socket_write wrapper function. */intJOEsocket_write( CONN *C, const void *buf, size_t len ){  int bytes;  int type;  if( C->prot == HTTPS ){    /* handle HTTPS protocol */    #ifdef HAVE_SSL    if(( bytes = ssl_socket_write( C, buf, len )) != len ){      perror( "JOEssl_socket_write: ERROR" );      return -1;    }    #else      perror( "JOEssl_socket_write: protocol NOT supported" );      return -1;    #endif/*HAVE_SSL*/  }  else{    /* assume HTTP */    if(( bytes = socket_write( C->sock, buf, len )) != len ){      perror( "JOEsocket_write: ERROR" );      return -1;    }  }  return 0;} /** * returns void * frees ssl resources if using ssl and * closes the connection and the socket. */voidJOEclose( CONN *C ){  int type;  #ifdef  HAVE_SSL    if( C->prot == HTTPS ){      SSL_shutdown( C->ssl );    }    SSL_free( C->ssl );    SSL_CTX_free( C->ctx );  #endif/*HAVE_SSL*/  close( C->sock );   return;} 

⌨️ 快捷键说明

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