modules/sk/cd_socket.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. SK_cd_make
  2. SK_cd_free
  3. SK_cd_puts
  4. SK_cd_gets
  5. SK_cd_close
  6. SK_cd_printf

   1 /***************************************
   2   $Revision: 1.5 $
   3 
   4   Socket module - cd_socket.c - basic read/write socket routines defined
   5                                 in terms of connection data structures
   6                                 with timeouts and storing information about
   7                                 broken connections.
   8 
   9   Status: NOT REVUED, TESTED
  10 
  11   Design and implementation by Marek Bukowy.
  12 
  13   ******************/ /******************
  14   Copyright (c) 1999, 2000, 2001                     RIPE NCC
  15  
  16   All Rights Reserved
  17   
  18   Permission to use, copy, modify, and distribute this software and its
  19   documentation for any purpose and without fee is hereby granted,
  20   provided that the above copyright notice appear in all copies and that
  21   both that copyright notice and this permission notice appear in
  22   supporting documentation, and that the name of the author not be
  23   used in advertising or publicity pertaining to distribution of the
  24   software without specific, written prior permission.
  25   
  26   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  27   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  28   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  29   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  30   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  31   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  32   ***************************************/
  33 
  34 #include "rip.h"
  35 
  36 /*+
  37  * -------------------------------------------------------------------
  38  * CD (connection data structure) varieties of the functions: 
  39  *   broken connections get registered in the connection structure
  40  *   as side effects.
  41  * by marek
  42  * -----------------------------------------------------------------
  43 +*/
  44 
  45 /* SK_cd_make */
  46 /*++++++++++++++++++++++++++++++++++++++
  47   
  48   Construct a connection data given the socket or file descriptor.
  49   Also performs the getpeername check and stores the IP in an allocated
  50   string.
  51 
  52   sk_conn_st *condat    pointer to where the data is to be stored.
  53 
  54   int  sock             The socket or file descriptor.
  55 
  56   unsigned timeout      Read timeout (used in SK_cd_gets) in seconds.
  57                         Value of 0 disables the timeout.
  58   ++++++++++++++++++++++++++++++++++++++*/
  59 void SK_cd_make(sk_conn_st *condat, int  sock, unsigned timeout)
     /* [<][>][^][v][top][bottom][index][help] */
  60 {
  61   memset(condat, 0, sizeof(sk_conn_st));
  62 
  63   condat->sock = sock;
  64 
  65   condat->ip = SK_getpeername(sock); 
  66   dieif(condat->ip == NULL);
  67 
  68   SK_getpeerip(sock, &(condat->rIP));
  69   condat->eIP =  condat->rIP;
  70 
  71   condat->rd_timeout.tv_sec = timeout;
  72 }
  73 
  74 
  75 /*++++++++++++++++++++++++++++++++++++++
  76   Destroys the data allocated and anchored by the connection data structure.
  77 
  78   sk_conn_st *condat   Pointer to the connection data structure.
  79 
  80   ++++++++++++++++++++++++++++++++++++++*/
  81 void SK_cd_free(sk_conn_st *condat)
     /* [<][>][^][v][top][bottom][index][help] */
  82 {
  83   UT_free(condat->ip);
  84 }
  85 
  86 /* SK_cd_puts() */
  87 /*++++++++++++++++++++++++++++++++++++++
  88 
  89    This function writes a character string out to a socket, unless 
  90    the connection is broken. 
  91 
  92    int SK_cd_puts         Returns the total_count of bytes written, 
  93                           or inverted error codes (negative numbers):
  94                           (- SK_DISCONNECT) on broken connection,
  95                           (- SK_INTERRUPT)  on control-c received,
  96                           (- SK_TIMEOUT)    on timeout.
  97 
  98    sk_conn_st *condat     Pointer to the connection data structure.
  99 
 100    char   *str            The buffer to be written to the socket.
 101 
 102   More:
 103        if the connection structure has bad status for this connection
 104        from previous calls, no write will be attempted.
 105 
 106   +html+ <PRE>
 107 
 108   Side Effects:
 109        broken connections get registered in the connection structure 
 110         
 111   +html+ </PRE>
 112 
 113   ++++++++++++++++++++++++++++++++++++++*/
 114 int SK_cd_puts(sk_conn_st *condat, const char *str) 
     /* [<][>][^][v][top][bottom][index][help] */
 115 {
 116   int res;
 117   struct timeval *ptm;
 118   
 119   /* if we're not connected, return our status */
 120   if (condat->rtc != 0)  {
 121     return (-condat->rtc);
 122   }
 123 
 124   /* bad design to use 0 to mean "infinity", but we'll keep it because
 125      that's the current implementation - shane */
 126   ptm = &condat->rd_timeout;
 127   if ((ptm->tv_sec == 0) && (ptm->tv_usec == 0)) { /* if timeout 0, 
 128                                                       do blocking I/O */
 129     ptm = NULL;
 130   }
 131 
 132   /* use SK_puts() to do the actual work */
 133   res = SK_puts(condat->sock, str, ptm);
 134 
 135   /* if timed out (or some other error), then set the rtc variable */
 136   if (res < 0) {
 137     condat->rtc |= SK_DISCONNECT;
 138     res = -SK_DISCONNECT;
 139   }
 140 
 141   /* return documented value */
 142   return res;
 143 } /* SK_cd_puts() */
 144 
 145 /* SK_cd_gets() */
 146 /*++++++++++++++++++++++++++++++++++++++
 147 
 148   Read from a socket, until a linefeed character is received or the buffer
 149   fills up to the maximum size "count". If the connection data has non-zero
 150   timeout value for reading, it is used here between calls to read 
 151   the next 1 character.
 152 
 153    int SK_cd_gets      Returns the total_count of bytes read, 
 154                        or inverted error codes (negative numbers):
 155                        (- SK_DISCONNECT) on broken connection,
 156                        (- SK_TIMEOUT)    on timeout.
 157 
 158    sk_conn_st *condat  connection data
 159 
 160    char   *str         The buffer to store the data received from
 161                        the socket.
 162 
 163    size_t count        size of the buffer.
 164 
 165   More:
 166        if the connection structure has bad status for this connection
 167        from previous calls, no read will be attempted.
 168 
 169   +html+ <PRE>
 170   Author:
 171         marek
 172         
 173   Side Effects:
 174        broken connections get registered in the connection structure.
 175        
 176   +html+ </PRE>
 177 
 178   ++++++++++++++++++++++++++++++++++++++*/
 179 int SK_cd_gets(sk_conn_st *condat, char *str, size_t count) 
     /* [<][>][^][v][top][bottom][index][help] */
 180 {
 181   fd_set rset;
 182   struct timeval *ptm = & condat->rd_timeout;
 183   int readcount = 0;
 184     
 185   memset( str, 0, count);
 186   /* leave space for \0 */
 187   count--;
 188 
 189   FD_ZERO( &rset );
 190   FD_SET( condat->sock, &rset );
 191 
 192   if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined, 
 193                                                   do blocking I/O */
 194     ptm = NULL;
 195   }
 196 
 197   do {
 198     char buf[2];
 199     int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);
 200 
 201     if (sel < 0) {
 202       /* unfortunate, but bad things happen to good sockets - SK */
 203       ER_perror(FAC_SK, SK_SELECT, "(%d) %s", errno, strerror(errno));
 204       break;
 205     }
 206       
 207     if( sel == 0 ) {      
 208       condat->rtc |= SK_TIMEOUT;
 209       break;
 210     }
 211 
 212     else { 
 213       if(read( condat->sock, buf, 1) == 0 ) {
 214         condat->rtc |= SK_DISCONNECT;
 215         break;
 216       }
 217       str[readcount] = buf[0];
 218       readcount++;
 219       if( buf[0] == '\n' ) {
 220         break;
 221       }
 222     } 
 223   } while( readcount < count );
 224          
 225   return readcount;
 226 
 227 } /* SK_cd_gets() */
 228 
 229 
 230 /*++++++++++++++++++++++++++++++++++++++
 231   Wrapper around the close(2) system call, 
 232 
 233   int SK_cd_close         returns the error codes of close(2).
 234 
 235   sk_conn_st *condat      Pointer to the connection data structure.
 236 
 237     +html+ <PRE>
 238   Author:
 239         marek
 240     +html+ </PRE>
 241   ++++++++++++++++++++++++++++++++++++++*/
 242 int SK_cd_close(sk_conn_st *condat) {
     /* [<][>][^][v][top][bottom][index][help] */
 243   return SK_close(condat->sock);
 244 } /* SK_cd_close() */
 245 
 246 
 247 /* SK_cd_printf() */
 248 /*++++++++++++++++++++++++++++++++++++++
 249 
 250   Printf-like function to print to socket/file specified by connection
 251   data structure. First writes the text to a temporary buffer, then
 252   uses SK_cd_puts to print it. Maintains a 2K static buffer, and allocates
 253   more memory if this is not enough.
 254 
 255   int SK_cd_printf       Returns the SK_cd_puts error code/return value.
 256 
 257   sk_conn_st *condat     Pointer to the connection data structure.
 258 
 259   char *txt              Format text to be written
 260 
 261   ...                    more arguments (like printf)
 262 
 263   
 264     +html+ <PRE>
 265   Author:
 266         marek
 267     +html+ </PRE>
 268   ++++++++++++++++++++++++++++++++++++++*/
 269 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
     /* [<][>][^][v][top][bottom][index][help] */
 270 {
 271 #define SKBUFLEN 2047
 272   va_list   ap;
 273   char      buffer[SKBUFLEN+1];
 274   unsigned  len;
 275   char      *newbuf = NULL;
 276   char      *finalbuf = buffer; /* points to where the text REALLY is */
 277  
 278   /* vsnprintf returns the number of character it WOULD write if it could.
 279      So we assume the buffer to be of adequate size for most cases,
 280      and if it isn't, then we allocate to newbuf and call v*printf again 
 281   */
 282   va_start(ap, txt);
 283   len = vsnprintf(buffer, SKBUFLEN, txt, ap);
 284   va_end(ap);
 285   
 286   if( len > SKBUFLEN ) {
 287     newbuf = (char *)UT_malloc(len+1);
 288     
 289     va_start(ap, txt);
 290     vsnprintf(newbuf, len, txt, ap);
 291     va_end(ap);   
 292     
 293     finalbuf = newbuf;
 294   }  
 295   /* terminate */
 296   finalbuf[len] = 0;
 297 
 298   /* reuse len */
 299   len = SK_cd_puts(condat, finalbuf);
 300 
 301   if(newbuf != NULL) {
 302     UT_free(newbuf);
 303   }
 304 
 305   return len;
 306 } /* SK_cd_printf() */

/* [<][>][^][v][top][bottom][index][help] */