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

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