## 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.2 $
       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   /* leave space for \0 */
     188   count--;
     189
     190   FD_ZERO( &rset );
     191   FD_SET( condat->sock, &rset );
     192
     193   if( ptm->tv_sec == 0 && ptm->tv_usec == 0) { /* if timeout undefined,
     194                                                   do blocking I/O */
     195     ptm = NULL;
     196   }
     197
     198   do {
     199     char buf[2];
     200     int sel = select( (condat->sock)+1, &rset, NULL, NULL, ptm);
     201     int ern = errno;
     202
     203     dieif(sel < 0); /* we don't expect problems */
     204
     205     if( sel == 0 ) {
     206       condat->rtc |= SK_TIMEOUT;
     207       break;
     208     }
     209
     210     else {
     211       if(read( condat->sock, buf, 1) == 0 ) {
     212         condat->rtc |= SK_DISCONNECT;
     213         break;
     214       }
     215       str[readcount] = buf[0];
     216       readcount++;
     217       if( buf[0] == '\n' ) {
     218         break;
     219       }
     220     }
     221   } while( readcount < count );
     222
     223   return readcount;
     224
     225 } /* SK_cd_gets() */
     226
     227
     228 /*++++++++++++++++++++++++++++++++++++++
     229   Wrapper around the close(2) system call,
     230
     231   int SK_cd_close         returns the error codes of close(2).
     232
     233   sk_conn_st *condat      Pointer to the connection data structure.
     234
     235     +html+ <PRE>
     236   Author:
     237         marek
     238     +html+ </PRE>
     239   ++++++++++++++++++++++++++++++++++++++*/
     240 int SK_cd_close(sk_conn_st *condat) {
         /* [<][>][^][v][top][bottom][index][help] */
     241   return SK_close(condat->sock);
     242 } /* SK_cd_close() */
     243
     244
     245 /* SK_cd_printf() */
     246 /*++++++++++++++++++++++++++++++++++++++
     247
     248   Printf-like function to print to socket/file specified by connection
     249   data structure. First writes the text to a temporary buffer, then
     250   uses SK_cd_puts to print it. Maintains a 2K static buffer, and allocates
     251   more memory if this is not enough.
     252
     253   int SK_cd_printf       Returns the SK_cd_puts error code/return value.
     254
     255   sk_conn_st *condat     Pointer to the connection data structure.
     256
     257   char *txt              Format text to be written
     258
     259   ...                    more arguments (like printf)
     260
     261
     262     +html+ <PRE>
     263   Author:
     264         marek
     265     +html+ </PRE>
     266   ++++++++++++++++++++++++++++++++++++++*/
     267 int SK_cd_printf(sk_conn_st *condat, char *txt, ...)
         /* [<][>][^][v][top][bottom][index][help] */
     268 {
     269 #define SKBUFLEN 2047
     270   va_list   ap;
     271   char      buffer[SKBUFLEN+1];
     272   unsigned  len;
     273   char      *newbuf = NULL;
     274   char      *finalbuf = buffer; /* points to where the text REALLY is */
     275
     276   /* vsnprintf returns the number of character it WOULD write if it could.
     277      So we assume the buffer to be of adequate size for most cases,
     278      and if it isn't, then we allocate to newbuf and call v*printf again
     279   */
     280   va_start(ap, txt);
     281   len = vsnprintf(buffer, SKBUFLEN, txt, ap);
     282   va_end(ap);
     283
     284   if( len > SKBUFLEN ) {
     285     dieif(!NOERR(wr_malloc( (void **)& newbuf, len+1)));
     286
     287     va_start(ap, txt);
     288     vsnprintf(newbuf, len, txt, ap);
     289     va_end(ap);
     290
     291     finalbuf = newbuf;
     292   }
     293   /* terminate */
     294   finalbuf[len] = 0;
     295
     296   /* reuse len */
     297   len = SK_cd_puts(condat, finalbuf);
     298
     299   if(newbuf != NULL) {
     300     wr_free(newbuf);
     301   }
     302
     303   return len;
     304 } /* SK_cd_printf() */

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