modules/sk/sk_socket.c

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

FUNCTIONS

This source file includes following functions.
  1. SK_atoport
  2. SK_close
  3. SK_getsock
  4. SK_accept_connection
  5. SK_connect
  6. SK_read
  7. SK_write
  8. SK_gets
  9. SK_puts
  10. SK_putc
  11. SK_getc
  12. SK_getpeername
  13. SK_getpeerip

   1 /***************************************
   2   $Revision: 1.18 $
   3 
   4   Socket module - routines facilitating calls to socket library.
   5 
   6   Status: NOT REVUED, TESTED
   7 
   8   Basic code adapted by Chris Ottrey from 
   9       http://www.ibrado.com/sock-faq/sfaq.html#faq65 - sample source code.
  10   ******************/ /******************
  11   Modification History:
  12         ottrey (08/03/1999) Created from sockhelp.c.
  13         ottrey (08/03/1998) Heavily butchered.
  14         joao   (22/06/1999) Modified socket creation and accepts.
  15         marek  (December 2000) Added connection function w/timeout.
  16   ******************/ /******************
  17   Copyright (c) 1999, 2000                           RIPE NCC
  18  
  19   All Rights Reserved
  20   
  21   Permission to use, copy, modify, and distribute this software and its
  22   documentation for any purpose and without fee is hereby granted,
  23   provided that the above copyright notice appear in all copies and that
  24   both that copyright notice and this permission notice appear in
  25   supporting documentation, and that the name of the author not be
  26   used in advertising or publicity pertaining to distribution of the
  27   software without specific, written prior permission.
  28   
  29   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  30   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  31   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  32   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  33   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  34   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  35   ***************************************/
  36 
  37 #include "sk.h"
  38 #include "constants.h"
  39 #include "stubs.h"
  40 
  41 #include "memwrap.h"
  42 
  43 /*+ String sizes +*/
  44 #define STR_S   63
  45 #define STR_XXL 16383
  46 
  47 /* SK_atoport() */
  48 /*++++++++++++++++++++++++++++++++++++++
  49    Take a service name, and a service type, and return a port number.  If the
  50    service name is not found, it tries it as a decimal number.  The number
  51    returned is byte ordered for the network.
  52 
  53   char *service   Service name (or port number).
  54 
  55   char *proto     Protocol (eg "tcp").
  56 
  57   Author:
  58         ottrey.
  59 
  60   ++++++++++++++++++++++++++++++++++++++*/
  61 int SK_atoport(const char *service, const char *proto) {
     /* [<][>][^][v][top][bottom][index][help] */
  62   unsigned port;
  63   long int lport;
  64   struct servent *serv;
  65   char *errpos;
  66   struct servent result;
  67   char buffer[STR_XXL];
  68 
  69   /* First try to read it from /etc/services */
  70 
  71 #ifdef __linux__
  72   if(getservbyname_r(service, proto, &result, buffer, sizeof(buffer), &serv) < 0) serv = NULL;
  73 #else  
  74   serv = getservbyname_r(service, proto, &result, buffer, sizeof(buffer));
  75 #endif
  76   
  77   if (serv != NULL)
  78     port = serv->s_port;
  79   else { /* Not in services, maybe a number? */
  80     lport = strtol(service,&errpos,0);
  81     if ( (errpos[0] != 0) || (lport < 1) || (lport > 65535) )
  82       return -1; /* Invalid port address */
  83     port = htons(lport);
  84   }
  85   return port;
  86 } /* SK_atoport() */
  87 
  88 
  89 /* SK_close() */
  90 /*++++++++++++++++++++++++++++++++++++++
  91   
  92   int SK_close     wrapper around closing the socket. Returns the value
  93                    returned by close(2)
  94 
  95   int socket       socket to be closed
  96 
  97   Author:
  98         ottrey
  99   ++++++++++++++++++++++++++++++++++++++*/
 100 int SK_close(int socket) {
     /* [<][>][^][v][top][bottom][index][help] */
 101   ER_dbg_va(FAC_SK, ASP_SK_GEN, "Closing socket... %d", socket);
 102 
 103   return close(socket);
 104 }
 105 
 106 /* SK_getsock() */
 107 /*++++++++++++++++++++++++++++++++++++++
 108 
 109    int  SK_getsock        This function creates a socket and binds to it. 
 110                           Returns the number of the created 
 111                           descriptor/listening socket.
 112 
 113    int socket_type        SOCK_STREAM or SOCK_DGRAM (TCP or UDP sockets)
 114 
 115    unsigned  port         The port to listen on. Ports < 1024 are
 116                           reserved for the root user. Host byte order.
 117 
 118    int backlog            Size of the backlog queue to be set on that
 119                           socket.
 120 
 121    uint32_t bind_address  Address to bind to, in network order.
 122 
 123   Authors:
 124         ottrey,
 125         joao,
 126         marek (added htons conversion for port).
 127 
 128   ++++++++++++++++++++++++++++++++++++++*/
 129 int  SK_getsock(int socket_type, unsigned h_port, int backlog, 
     /* [<][>][^][v][top][bottom][index][help] */
 130                 uint32_t bind_address) {
 131   struct sockaddr_in address;
 132   int listening_socket;
 133   int reuse_addr = 1;
 134   u_short port = htons(h_port);
 135 
 136   /* Setup internet address information.  
 137      This is used with the bind() call */
 138   memset((char *) &address, 0, sizeof(address));
 139   address.sin_family = AF_INET;
 140   address.sin_port = port;
 141   address.sin_addr.s_addr = bind_address;
 142 
 143   /* Map all of the signals and exit routine */
 144 
 145   listening_socket = socket(AF_INET, socket_type, 0);
 146   if (listening_socket < 0) {
 147     perror("socket");
 148     exit(EXIT_FAILURE);
 149   }
 150 
 151   setsockopt(listening_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse_addr, sizeof(reuse_addr));
 152 
 153   if (bind(listening_socket, (struct sockaddr *) &address, sizeof(address)) < 0) {
 154     perror("bind");
 155     close(listening_socket);
 156     exit(EXIT_FAILURE);
 157   }
 158 
 159 
 160   if (socket_type == SOCK_STREAM) {
 161     listen(listening_socket, backlog); /* Queue up to five connections before
 162                                   having them automatically rejected. */
 163   }
 164 
 165   return listening_socket;
 166 } /* SK_getsock() */
 167 
 168 /*++++++++++++++++++++++++++++++++++++++
 169 
 170    Wait for an incoming connection on the specified socket
 171 
 172    int  SK_accept_connection The socket for communicating to the client
 173 
 174    int  listening_socket     The socket that the server is bound to
 175 
 176   Authors:
 177         joao,
 178         marek.
 179   ++++++++++++++++++++++++++++++++++++++*/
 180 int SK_accept_connection(int listening_socket) {
     /* [<][>][^][v][top][bottom][index][help] */
 181   int connected_socket = -1;
 182   int num_errors = 0;
 183 
 184 #define MAX_ACCEPT_ERRORS 3
 185 
 186   for (;;) {
 187     
 188     ER_dbg_va(FAC_SK, ASP_SK_GEN, 
 189               "Going to accept connections on socket : %d",listening_socket);
 190 
 191     connected_socket = accept(listening_socket, NULL, NULL);
 192     if (connected_socket < 0) {
 193       /* Either a real error occured, or blocking was interrupted for
 194          some reason.  Only abort execution if a real error occured. */
 195       switch(errno) {
 196       case EINTR:        /* Interrupted system call */
 197       case ECONNABORTED: /* Software caused connection abort */
 198         /* no warning */
 199         continue;    /* don't return - do the accept again */
 200       default: 
 201         /* special case: shutdown of the server - just return */
 202         if( CO_get_do_server() == 0 ) {
 203           return -1;
 204         }
 205         else { /* real error */
 206           if( ++num_errors < MAX_ACCEPT_ERRORS ) {
 207             /* warn */
 208             ER_perror(FAC_SK, SK_ACERW, "(%d) %s", errno, strerror(errno));
 209           }
 210           else {
 211             /* crash */
 212             ER_perror(FAC_SK, SK_ACERF, 
 213                 "too many accept() errors (maximum is %d)", MAX_ACCEPT_ERRORS);
 214             die;
 215           }
 216         }
 217       }
 218     } 
 219     else { /* success */
 220        ER_dbg_va(FAC_SK, ASP_SK_GEN, "client connected on socket %d", 
 221             connected_socket
 222             );
 223 
 224        return connected_socket;
 225     }
 226 
 227   }
 228 }
 229 
 230 
 231 /*++++++++++++++++++++++++++++++++++++++
 232   
 233   er_ret_t SK_connect       wrapper around connect(), doing non-blocking 
 234                             connection with timeout 
 235 
 236   int *sock         pointer to the storage for socket descriptor 
 237    
 238   char *hostname    host to connect to
 239 
 240   int port          port to connect to
 241 
 242   int timeout       in seconds
 243 
 244   Author: marek
 245 
 246   ++++++++++++++++++++++++++++++++++++++*/
 247 er_ret_t SK_connect(int  *sock, char *hostname, unsigned int port, unsigned int timeout)
     /* [<][>][^][v][top][bottom][index][help] */
 248 {
 249   struct sockaddr_in sin;
 250   struct hostent *hp;
 251   int s;
 252   int flags;
 253   struct timeval ptm;
 254   fd_set rset, wset;
 255   int gs, sel, er, erlen=sizeof(er);
 256   int error;
 257   struct hostent result;
 258   char aliasbuf[8192]; /* Stevens, UNIX net. prog., p.304 */
 259 
 260   /* look up the host name */
 261 #ifdef __linux__
 262   er = (gethostbyname_r(hostname,  &result, aliasbuf, 
 263                         sizeof(aliasbuf), &hp, &error) < 0 );
 264 #else /* default is Solaris implementation */                             
 265   hp = gethostbyname_r(hostname,  &result, aliasbuf, 
 266                        sizeof(aliasbuf), &error);
 267   er = ( hp == NULL ); 
 268 #endif      
 269   
 270   if( er ) {
 271     return SK_BADHOST;
 272   }
 273   
 274   /* create a socket */
 275   s = socket(AF_INET, SOCK_STREAM, 0);
 276   if (s < 0) {
 277     return SK_SOCKET;
 278   }
 279   
 280   /* bind to it */
 281   bzero((caddr_t)&sin, sizeof (sin));
 282   sin.sin_family = hp->h_addrtype;
 283   if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
 284     close(s);
 285     return SK_BIND;
 286   }
 287   bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
 288   sin.sin_port=htons(port);
 289 
 290   /* connect in non-blocking mode */
 291   flags = fcntl(s, F_GETFL, 0);
 292   fcntl(s, F_SETFL, flags | O_NONBLOCK );
 293 
 294   if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0
 295       && errno != EINPROGRESS ) {
 296     close(s);
 297     return SK_CONNECT;
 298   }
 299   
 300   /* now wait for success */
 301   FD_ZERO( &rset );
 302   FD_SET( s, &rset );
 303   wset = rset;
 304   ptm.tv_usec = 0;
 305   ptm.tv_sec = timeout;
 306   
 307   if( (sel=select(s+1,  &rset, &wset, NULL, &ptm)) == 0 ) {
 308     /* timeout */
 309     close(s);
 310     return SK_TIMEOUT;
 311   }
 312   if (sel < 0) {
 313     close(s);
 314     return SK_CONNECT;
 315   }
 316   
 317   gs = getsockopt(s, SOL_SOCKET, SO_ERROR, &er, &erlen);
 318   
 319   if( gs < 0 || er ) {   /* Stevens code, p.411 is exceptionally crappy */
 320     close(s);
 321     return SK_CONNECT;
 322   } /* if error */
 323   
 324   fcntl(s, F_SETFL, flags);
 325   *sock = s;
 326   
 327   return SK_OK;
 328 }
 329 
 330 
 331 /* SK_read() */
 332 /*++++++++++++++++++++++++++++++++++++++
 333 
 334    This is just like the read() system call, except that it will make
 335    sure that all your data goes through the socket.
 336 
 337    int    SK_read   Returns the number of bytes read.
 338 
 339    int    sockfd    The socket file descriptor.
 340 
 341    char   *buf      The buffer to be read from the socket.
 342 
 343    size_t count     The number of bytes in the buffer.
 344 
 345   Author:
 346         ottrey
 347 
 348   ++++++++++++++++++++++++++++++++++++++*/
 349 int SK_read(int sockfd, char *buf, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 350   size_t bytes_read = 0;
 351   int this_read;
 352 
 353   while (bytes_read < count) {
 354     do
 355       this_read = read(sockfd, buf, count - bytes_read);
 356     while ( (this_read < 0) && (errno == EINTR) );
 357     if (this_read < 0)
 358       return this_read;
 359     else if (this_read == 0)
 360       return bytes_read;
 361     bytes_read += this_read;
 362     buf += this_read;
 363   }
 364 
 365   return count;
 366 
 367 } /* SK_read() */
 368 
 369 
 370 /* SK_write() */
 371 /*++++++++++++++++++++++++++++++++++++++
 372 
 373    int SK_write   Returns:
 374                      -1 on error
 375                       0 on timeout 
 376                       1 on success (all bytes written)
 377 
 378    int sockfd                      The socket file descriptor.
 379 
 380    const char *buf                 The buffer to be written to the socket.
 381 
 382    int count                       The number of bytes in the buffer.
 383 
 384    const struct timeval *timeout   Maximum time to wait between each 
 385                                    write() call, or NULL for "forever".
 386 
 387    int *count_sent                 Set to the number of bytes sucessfully
 388                                    written.  This value is always valid, 
 389                                    although it will be less than the 
 390                                    total number of bytes to send if 
 391                                    the function returns -1 or 0.  NULL
 392                                    may be sent if the caller does not
 393                                    care about the number of bytes sent on
 394                                    failure.
 395 
 396   ++++++++++++++++++++++++++++++++++++++*/
 397 
 398 int 
 399 SK_write(int sockfd, 
     /* [<][>][^][v][top][bottom][index][help] */
 400          const char *buf,
 401          int count,
 402          const struct timeval *timeout, 
 403          int *count_sent) 
 404 {
 405   int     local_count_sent;    /* only used if caller passes NULL */
 406   fd_set  fds;
 407   int     select_ret;
 408   struct  timeval tv;
 409   int     write_ret;
 410   
 411   /* copious logging never hurt anybody (well, except people with slow
 412      computers or small hard disks) */
 413   ER_dbg_va(FAC_SK, ASP_SK_WRIT,
 414             "SK_write = { sockfd=[%d], buf=[%s], count=[%d]", 
 415             sockfd, buf, count);
 416 
 417   /* allow caller to pass NULL if it doesn't care about the count sent */
 418   if (count_sent == NULL) {
 419       count_sent = &local_count_sent;
 420   }
 421 
 422   /* loop around until we send all of our data, or we get a timeout or
 423      disconnect */
 424   *count_sent = 0;
 425   while (*count_sent < count) {
 426 
 427     /* first, call select() and see if we can write without blocking */
 428     FD_ZERO(&fds);
 429     FD_SET(sockfd, &fds);
 430     if (timeout == NULL) {
 431         select_ret = select(sockfd+1, NULL, &fds, NULL, NULL);
 432     } else {
 433         /* make a copy of timeout, because it's value is undefined 
 434            on return from select() */
 435         tv = *timeout;
 436         select_ret = select(sockfd+1, NULL, &fds, NULL, &tv);
 437     }
 438     /* check for error */
 439     if (select_ret < 0) {
 440         /* log the error and return "timeout" */
 441         ER_perror(FAC_SK, SK_SELECT, "(%d) %s", errno, strerror(errno));
 442         return -1;
 443     }
 444     /* check for timeout */
 445     if ((select_ret == 0) || !FD_ISSET(sockfd, &fds)) {
 446         return -1;
 447     }
 448 
 449 
 450     /* at this point we can safely write */
 451     write_ret = write(sockfd, buf, count - *count_sent);
 452 
 453     /* if write failed, assume other side disconnected */
 454     if (write_ret <= 0) {
 455         return 0;
 456     }
 457 
 458     /* update our current status */
 459     *count_sent += write_ret;
 460     buf += write_ret;
 461 
 462   }
 463 
 464   /* all bytes sent, return success */
 465   return 1;
 466 } /* SK_write() */
 467 
 468 
 469 /* SK_gets() */
 470 /*++++++++++++++++++++++++++++++++++++++
 471 
 472    This function reads from a socket, until it recieves a linefeed
 473    character.  It fills the buffer "str" up to the maximum size "count".
 474 
 475    int SK_gets      Returns the total_count of bytes read.
 476 
 477    int    sockfd    The socket file descriptor.
 478 
 479    char   *str      The buffer to be written from the socket.
 480 
 481    size_t count     The number of bytes in the buffer.
 482 
 483 
 484   Authors:
 485         ottrey,
 486         marek (modified for meaningful error codes).
 487 
 488   Side Effects:
 489         This function will return -1 if the socket is closed during the read operation.
 490 
 491         Note that if a single line exceeds the length of count, the extra data
 492         will be read and discarded!  You have been warned.
 493 
 494   ++++++++++++++++++++++++++++++++++++++*/
 495 int SK_gets(int  sockfd, char *str, size_t count) {
     /* [<][>][^][v][top][bottom][index][help] */
 496   int bytes_read;
 497   int total_count = 0;
 498   char *current_position;
 499   char last_read = 0;
 500 
 501   int control_c = 0;
 502 
 503   current_position = str;
 504   while (last_read != 10) {
 505 
 506     bytes_read = read(sockfd, &last_read, 1);
 507     if (bytes_read <= 0) {
 508       /* The other side may have closed unexpectedly */
 509       return SK_DISCONNECT; 
 510       /* Is this effective on other platforms than linux? */
 511     }
 512     if ( (total_count < count) && (last_read != 10) && (last_read !=13) ) {
 513       *current_position = last_read;
 514       current_position++;
 515       total_count++;
 516     }
 517 
 518     if (last_read == -1) {
 519       bytes_read = read(sockfd, &last_read, 1);
 520       if (last_read == -12) {
 521         ER_dbg_va(FAC_SK, ASP_SK_GEN,"Client pressed Control-c");
 522         control_c = 1;
 523         ER_dbg_va(FAC_SK, ASP_SK_GEN,"returning SK_INTERRUPT");
 524         return SK_INTERRUPT;
 525       }
 526     }
 527   }
 528   if (count > 0) {
 529     *current_position = 0;
 530   }
 531 
 532   return total_count;
 533 
 534 } /* SK_gets() */
 535 
 536 
 537 /* SK_puts() */
 538 /*++++++++++++++++++++++++++++++++++++++
 539 
 540    This function writes a character string out to a socket.
 541 
 542    int SK_puts  The total_count of bytes written, 
 543                 or -1 on hangup, error, or timeout
 544 
 545    int    sockfd    The socket file descriptor.
 546 
 547    char   *str      The buffer to be written from the socket.
 548 
 549    const struct timeval *timeout   Maximum time to wait between each 
 550                                    write() call, or NULL for "forever".
 551 
 552   ++++++++++++++++++++++++++++++++++++++*/
 553 int 
 554 SK_puts(int sockfd, const char *str, const struct timeval *timeout) 
     /* [<][>][^][v][top][bottom][index][help] */
 555 {
 556   int count_sent;
 557   if (SK_write(sockfd, str, strlen(str), timeout, &count_sent) <= 0) {
 558       return -1;
 559   } else {
 560       return count_sent;
 561   }
 562 } /* SK_puts() */
 563 
 564 /* SK_putc() */
 565 /*++++++++++++++++++++++++++++++++++++++
 566   
 567   This function writes a single character out to a socket.
 568 
 569    int SK_putc       Returns the number of characters written.
 570 
 571    int sockfd        socket
 572 
 573    char ch           character
 574 
 575    const struct timeval *timeout   Maximum time to wait between each 
 576                                    write() call, or NULL for "forever".
 577 
 578   ++++++++++++++++++++++++++++++++++++++*/
 579 int 
 580 SK_putc(int sockfd, char ch, const struct timeval *timeout) 
     /* [<][>][^][v][top][bottom][index][help] */
 581 {
 582   int count_sent;
 583   SK_write(sockfd, &ch, 1, timeout, &count_sent);
 584   return count_sent;
 585 }/* SK_putc() */
 586 
 587 /*++++++++++++++++++++++++++++++++++++++
 588 
 589    This function reads a single character from a socket.
 590 
 591    returns EOF when no character can be read. 
 592 
 593   ++++++++++++++++++++++++++++++++++++++*/
 594 int SK_getc(int  sockfd) {
     /* [<][>][^][v][top][bottom][index][help] */
 595   char ch;
 596 
 597   if( read(sockfd, &ch, 1) <= 0 ) {
 598     return EOF;
 599   }
 600   else {
 601     return ch;
 602   }
 603 }/* SK_getc() */
 604 
 605 /* SK_getpeername() */
 606 /*++++++++++++++++++++++++++++++++++++++
 607 
 608   This function will tell you who is at the other end of a connected stream socket.
 609   
 610   char *SK_getpeername     Returns allocated string with the IP in it, 
 611                            or "--" if the descriptor is not a socket,
 612                            or NULL on error.
 613 
 614   int    sockfd            The socket or file descriptor.
 615 
 616   +html+ <PRE>
 617   Authors:
 618         ottrey,
 619         marek (modified error handling, made MT-Safe).
 620   +html+ </PRE>
 621 
 622   ++++++++++++++++++++++++++++++++++++++*/
 623 char *SK_getpeername(int  sockfd) 
     /* [<][>][^][v][top][bottom][index][help] */
 624 {
 625   char *hostaddress=NULL;
 626   struct sockaddr_in addr_in;
 627   int namelen=sizeof(addr_in);
 628  
 629   if (getpeername(sockfd, (struct sockaddr *)&addr_in, &namelen) == 0) {
 630 
 631     dieif( wr_malloc((void **)&hostaddress, INET_ADDRSTRLEN) != UT_OK); 
 632     inet_ntop(AF_INET, &(addr_in.sin_addr),  hostaddress, INET_ADDRSTRLEN);
 633   }
 634   else {
 635     int er = errno;
 636     
 637     if( er == ENOTSOCK ) {
 638       hostaddress = wr_string("--");
 639     }
 640     else {
 641       /* XXX: hack to avoid crash in the case where peer disconnects */
 642       /* To fix this, the socket interface needs to deal with a structure
 643          containing not only the file descriptor, but also the address of
 644          the host and the peer.  Other goodies, like the current time, 
 645          time of last operation, and last errno could also be included
 646          for good measure. */
 647       hostaddress = UT_strdup("127.0.0.1");
 648     }
 649   }
 650 
 651   return hostaddress;
 652   
 653 } /* SK_getpeername() */
 654 
 655 
 656 /* SK_getpeerip */
 657 /*++++++++++++++++++++++++++++++++++++++
 658   
 659   This function will check the ip of the connected peer and store it in the
 660   ip_addr_t structure defined in the IP module.
 661 
 662   int SK_getpeerip    returns 0 on success, -1 on failure.
 663 
 664   int  sockfd         The socket descriptor (file will result in -1)
 665 
 666   ip_addr_t *ip       Pointer to where the address should be stored.
 667 
 668   +html+ <PRE>
 669   Author:
 670         marek
 671   +html+ </PRE>
 672   ++++++++++++++++++++++++++++++++++++++*/
 673 
 674 int SK_getpeerip(int  sockfd, ip_addr_t *ip) {
     /* [<][>][^][v][top][bottom][index][help] */
 675   struct sockaddr_in addr_in;
 676   int namelen=sizeof(addr_in);
 677   int ret=-1;
 678 
 679   memset(& addr_in, 0, sizeof(struct sockaddr_in));
 680 
 681   if (getpeername(sockfd, (struct sockaddr *)(& addr_in), &namelen) != -1) {
 682     ret=0;
 683     IP_addr_s2b(ip, &addr_in, namelen);
 684   } else {
 685       /* XXX: hack to avoid crash in the case where peer disconnects */
 686       /* To fix this, the socket interface needs to deal with a structure
 687          containing not only the file descriptor, but also the address of
 688          the host and the peer.  Other goodies, like the current time, 
 689          time of last operation, and last errno could also be included
 690          for good measure. */
 691       ret = 0;
 692       addr_in.sin_family = AF_INET;
 693       addr_in.sin_addr.s_addr = INADDR_LOOPBACK;
 694       addr_in.sin_port = 0;
 695       IP_addr_s2b(ip, &addr_in, namelen);
 696   }
 697   
 698   return ret;
 699 }
 700 

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