## 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.1 $
       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                           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 #include "sk.h"
      34 #include "stubs.h"
      35 #include "memwrap.h"
      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   wr_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   Author:
     108         marek
     109
     110   Side Effects:
     111        broken connections get registered in the connection structure
     112
     113   +html+ </PRE>
     114
     115   ++++++++++++++++++++++++++++++++++++++*/
     116 int SK_cd_puts(sk_conn_st *condat, const char *str)
         /* [<][>][^][v][top][bottom][index][help] */
     117 {
     118   int res;
     119
     120   if( condat->rtc != 0 ) {
     121     return (-condat->rtc);
     122   }
     123
     124   res = SK_puts(condat->sock, str);
     125
     126   if( res < 0 ){
     127     /* set the corresponding rtc flag */
     128     condat->rtc |= (-res);
     129
     130     switch( - res ) {
     131       /* dont know what to do and how to log */
     132     case SK_DISCONNECT:
     133     case SK_INTERRUPT:
     134       /*("Thread received a control-c\n");*/
     135     case SK_TIMEOUT:
     136       /*("Reading timed out\n");*/
     137       break;
     138     default:
     139       /* unexpected error code. bail out */
     140       die;
     141     }
     142   }
     143   return res;
     144 } /* SK_cd_puts() */
     145
     146 /* SK_cd_gets() */
     147 /*++++++++++++++++++++++++++++++++++++++
     148
     149   Read from a socket, until a linefeed character is received or the buffer
     150   fills up to the maximum size "count". If the connection data has non-zero
     151   timeout value for reading, it is used here between calls to read
     152   the next 1 character.
     153
     154    int SK_cd_gets      Returns the total_count of bytes read,
     155                        or inverted error codes (negative numbers):
     156                        (- SK_DISCONNECT) on broken connection,
     157                        (- SK_TIMEOUT)    on timeout.
     158
     159    sk_conn_st *condat  connection data
     160
     161    char   *str         The buffer to store the data received from
     162                        the socket.
     163
     164    size_t count        size of the buffer.
     165
     166   More:
     167        if the connection structure has bad status for this connection
     168        from previous calls, no read will be attempted.
     169
     170   +html+ <PRE>
     171   Author:
     172         marek
     173
     174   Side Effects:
     175        broken connections get registered in the connection structure.
     176
     177   +html+ </PRE>
     178
     179   ++++++++++++++++++++++++++++++++++++++*/
     180 int SK_cd_gets(sk_conn_st *condat, char *str, size_t count)
         /* [<][>][^][v][top][bottom][index][help] */
     181 {
     182   fd_set rset;
     183   struct timeval *ptm = & condat->rd_timeout;
     184   int readcount = 0;
     185
     186   memset( str, 0, count);
     187   FD_ZERO( &rset );
     188   FD_SET( condat->sock, &rset );
     189
     190   if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined,
     191                                                   do blocking I/O */
     192     ptm = NULL;
     193   }
     194
     195   do {
     196     char buf[2];
     197     int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);
     198     int ern = errno;
     199
     200     dieif(sel < 0); /* we don't expect problems */
     201
     202     if( sel == 0 ) {
     203       condat->rtc |= SK_TIMEOUT;
     204       break;
     205     }
     206
     207     else {
     208       if(read( condat->sock, buf, 1) == 0 ) {
     209         condat->rtc |= SK_DISCONNECT;
     210         break;
     211       }
     212       str[readcount] = buf[0];
     213       readcount++;
     214       if( buf[0] == '\n' ) {
     215         break;
     216       }
     217     }
     218   } while( readcount < count );
     219
     220   return readcount;
     221
     222 } /* SK_cd_gets() */
     223
     224
     225 /*++++++++++++++++++++++++++++++++++++++
     226   Wrapper around the close(2) system call,
     227
     228   int SK_cd_close         returns the error codes of close(2).
     229
     230   sk_conn_st *condat      Pointer to the connection data structure.
     231
     232     +html+ <PRE>
     233   Author:
     234         marek
     235     +html+ </PRE>
     236   ++++++++++++++++++++++++++++++++++++++*/
     237 int SK_cd_close(sk_conn_st *condat) {
         /* [<][>][^][v][top][bottom][index][help] */
     238   return SK_close(condat->sock);
     239 } /* SK_cd_close() */
     240
     241
     242 /* SK_cd_printf() */
     243 /*++++++++++++++++++++++++++++++++++++++
     244
     245   Printf-like function to print to socket/file specified by connection
     246   data structure. First writes the text to a temporary buffer, then
     247   uses SK_cd_puts to print it. Maintains a 2K static buffer, and allocates
     248   more memory if this is not enough.
     249
     250   int SK_cd_printf       Returns the SK_cd_puts error code/return value.
     251
     252   sk_conn_st *condat     Pointer to the connection data structure.
     253
     254   char *txt              Format text to be written
     255
     256   ...                    more arguments (like printf)
     257
     258
     259     +html+ <PRE>
     260   Author:
     261         marek
     262     +html+ </PRE>
     263   ++++++++++++++++++++++++++++++++++++++*/
     264 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
         /* [<][>][^][v][top][bottom][index][help] */
     265 {
     266 #define SKBUFLEN 2047
     267   va_list   ap;
     268   char      buffer[SKBUFLEN+1];
     269   unsigned  len;
     270   char      *newbuf = NULL;
     271   char      *finalbuf = buffer; /* points to where the text REALLY is */
     272
     273   /* vsnprintf returns the number of character it WOULD write if it could.
     274      So we assume the buffer to be of adequate size for most cases,
     275      and if it isn't, then we allocate to newbuf and call v*printf again
     276   */
     277   va_start(ap, txt);
     278   len = vsnprintf(buffer, SKBUFLEN, txt, ap);
     279   va_end(ap);
     280
     281   if( len > SKBUFLEN ) {
     282     dieif(!NOERR(wr_malloc( (void **)& newbuf, len+1)));
     283
     284     va_start(ap, txt);
     285     vsnprintf(newbuf, len, txt, ap);
     286     va_end(ap);
     287
     288     finalbuf = newbuf;
     289   }
     290   /* terminate */
     291   finalbuf[len] = 0;
     292
     293   /* reuse len */
     294   len = SK_cd_puts(condat, finalbuf);
     295
     296   if(newbuf != NULL) {
     297     wr_free(newbuf);
     298   }
     299
     300   return len;
     301 } /* SK_cd_printf() */

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