Annotation of sbbs/xpdev/sockwrap.c, revision 1.1.1.1

1.1       root        1: /* sockwrap.c */
                      2: 
                      3: /* Berkley/WinSock socket API wrappers */
                      4: 
                      5: /* $Id: sockwrap.c,v 1.24 2005/01/01 00:52:43 rswindell Exp $ */
                      6: 
                      7: /****************************************************************************
                      8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                     10:  *                                                                                                                                                     *
                     11:  * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html         *
                     12:  *                                                                                                                                                     *
                     13:  * This library is free software; you can redistribute it and/or                       *
                     14:  * modify it under the terms of the GNU Lesser General Public License          *
                     15:  * as published by the Free Software Foundation; either version 2                      *
                     16:  * of the License, or (at your option) any later version.                                      *
                     17:  * See the GNU Lesser General Public License for more details: lgpl.txt or     *
                     18:  * http://www.fsf.org/copyleft/lesser.html                                                                     *
                     19:  *                                                                                                                                                     *
                     20:  * Anonymous FTP access to the most recent released source is available at     *
                     21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     22:  *                                                                                                                                                     *
                     23:  * Anonymous CVS access to the development source and modification history     *
                     24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     26:  *     (just hit return, no password is necessary)                                                     *
                     27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     28:  *                                                                                                                                                     *
                     29:  * For Synchronet coding style and modification guidelines, see                                *
                     30:  * http://www.synchro.net/source.html                                                                          *
                     31:  *                                                                                                                                                     *
                     32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     33:  * format) via e-mail to [email protected]                                                                      *
                     34:  *                                                                                                                                                     *
                     35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     36:  ****************************************************************************/
                     37: 
                     38: #include <stdlib.h>            /* malloc/free on FreeBSD */
                     39: #include <string.h>            /* bzero (for FD_ZERO) on FreeBSD */
                     40: #include <errno.h>             /* ENOMEM */
                     41: #include <stdio.h>             /* SEEK_SET */
                     42: #include <string.h>
                     43: 
                     44: #include "genwrap.h"   /* SLEEP */
                     45: #include "gen_defs.h"  /* BOOL/LOG_WARNING */
                     46: #include "sockwrap.h"  /* sendsocket */
                     47: #include "filewrap.h"  /* filelength */
                     48: 
                     49: int sendfilesocket(int sock, int file, long *offset, long count)
                     50: {
                     51: /* sendfile() on Linux may or may not work with non-blocking sockets ToDo */
                     52: #if defined(__FreeBSD__) && 0
                     53: #warning FreeBSD sendfile may cause problems!
                     54:        off_t   total=0;
                     55:        off_t   wr=0;
                     56:        int             i;
                     57:        long    len;
                     58: 
                     59:        len=filelength(file);
                     60:        if(count<1 || count>len) {
                     61:                count=len;
                     62:                count-=offset==NULL?0:*offset;
                     63:        }
                     64:        while((i=sendfile(file,sock,(offset==NULL?0:*offset)+total,count-total,NULL,&wr,0))==-1 && errno==EAGAIN)  {
                     65:                total+=wr;
                     66:                SLEEP(1);
                     67:        }
                     68:        if(i==0)
                     69:                return((int)count);
                     70:        return(i);
                     71: #else
                     72:        char*   buf;
                     73:        long    len;
                     74:        int             rd;
                     75:        int             wr;
                     76:        int             total;
                     77: 
                     78:        if(offset!=NULL)
                     79:                if(lseek(file,*offset,SEEK_SET)<0)
                     80:                        return(-1);
                     81: 
                     82:        len=filelength(file);
                     83: 
                     84:        if(count<1 || count>len) {
                     85:                count=len;
                     86:                count-=tell(file);              /* don't try to read beyond EOF */
                     87:        }
                     88: 
                     89:        if((buf=(char*)malloc(count))==NULL) {
                     90:                errno=ENOMEM;
                     91:                return(-1);
                     92:        }
                     93: 
                     94:        rd=read(file,buf,count);
                     95:        if(rd!=count) {
                     96:                free(buf);
                     97:                return(-1);
                     98:        }
                     99: 
                    100:        for(total=wr=0;total<count;total+=wr) {
                    101:                wr=sendsocket(sock,buf+total,count-total);
                    102:                if(wr>0)
                    103:                        continue;
                    104:                if(wr==SOCKET_ERROR && ERROR_VALUE==EWOULDBLOCK) {
                    105:                        wr=0;
                    106:                        SLEEP(1);
                    107:                        continue;
                    108:                }
                    109:                break;
                    110:        }
                    111: 
                    112:        free(buf);
                    113: 
                    114:        if(offset!=NULL)
                    115:                (*offset)+=total;
                    116: 
                    117:        if(wr<1)
                    118:                return(wr);
                    119: 
                    120:        return(total);
                    121: #endif
                    122: }
                    123: 
                    124: int recvfilesocket(int sock, int file, long *offset, long count)
                    125: {
                    126:        /* Writes a file from a socket -
                    127:         *
                    128:         * sock         - Socket to read from
                    129:         * file         - File descriptior to write to
                    130:         *                              MUST be open and writeable
                    131:         * offset       - pointer to file offset to start writing at
                    132:         *                              is set to offset writing STOPPED
                    133:         *                              on return
                    134:         * count        - number of bytes to read/write
                    135:         *
                    136:         * returns -1 if an error occurse, otherwise
                    137:         * returns number ob bytes written and sets offset
                    138:         * to the new offset
                    139:         */
                    140:         
                    141:        char*   buf;
                    142:        int             rd;
                    143:        int             wr;
                    144: 
                    145:        if(count<1) {
                    146:                errno=ERANGE;
                    147:                return(-1);
                    148:        }
                    149:                
                    150:        if((buf=(char*)malloc(count))==NULL) {
                    151:                errno=ENOMEM;
                    152:                return(-1);
                    153:        }
                    154: 
                    155:        if(offset!=NULL)
                    156:                if(lseek(file,*offset,SEEK_SET)<0)
                    157:                        return(-1);
                    158: 
                    159:        rd=read(sock,buf,count);
                    160:        if(rd!=count) {
                    161:                free(buf);
                    162:                return(-1);
                    163:        }
                    164: 
                    165:        wr=write(file,buf,rd);
                    166:        free(buf);
                    167: 
                    168:        if(offset!=NULL)
                    169:                (*offset)+=wr;
                    170: 
                    171:        return(wr);
                    172: }
                    173: 
                    174: 
                    175: /* Return true if connected, optionally sets *rd_p to true if read data available */
                    176: BOOL socket_check(SOCKET sock, BOOL* rd_p, BOOL* wr_p, DWORD timeout)
                    177: {
                    178:        char    ch;
                    179:        int             i,rd;
                    180:        fd_set  rd_set;
                    181:        fd_set* rd_set_p=&rd_set;
                    182:        fd_set  wr_set;
                    183:        fd_set* wr_set_p=NULL;
                    184:        struct  timeval tv;
                    185: 
                    186:        if(rd_p!=NULL)
                    187:                *rd_p=FALSE;
                    188: 
                    189:        if(wr_p!=NULL)
                    190:                *wr_p=FALSE;
                    191: 
                    192:        if(sock==INVALID_SOCKET)
                    193:                return(FALSE);
                    194: 
                    195:        FD_ZERO(&rd_set);
                    196:        FD_SET(sock,&rd_set);
                    197:        if(wr_p!=NULL) {
                    198:                wr_set_p=&wr_set;
                    199:                FD_ZERO(wr_set_p);
                    200:                FD_SET(sock,wr_set_p);
                    201:                if(rd_p==NULL)
                    202:                        rd_set_p=NULL;
                    203:        }
                    204: 
                    205:        /* Convert timeout from ms to sec/usec */
                    206:        tv.tv_sec=timeout/1000;
                    207:        tv.tv_usec=(timeout%1000)*1000;
                    208: 
                    209:        i=select(sock+1,rd_set_p,wr_set_p,NULL,&tv);
                    210:        if(i==SOCKET_ERROR)
                    211:                return(FALSE);
                    212: 
                    213:        if(i==0) 
                    214:                return(TRUE);
                    215: 
                    216:        if(wr_p!=NULL && FD_ISSET(sock,wr_set_p)) {
                    217:                *wr_p=TRUE;
                    218:                if(i==1)
                    219:                        return(TRUE);
                    220:        }
                    221: 
                    222:        if(rd_p !=NULL || wr_p==NULL)  {
                    223:                rd=recv(sock,&ch,1,MSG_PEEK);
                    224:                if(rd==1 
                    225:                        || (rd==SOCKET_ERROR && ERROR_VALUE==EMSGSIZE)) {
                    226:                        if(rd_p!=NULL)
                    227:                                *rd_p=TRUE;
                    228:                        return(TRUE);
                    229:                }
                    230:        }
                    231: 
                    232:        return(FALSE);
                    233: }
                    234: 
                    235: int retry_bind(SOCKET s, const struct sockaddr *addr, socklen_t addrlen
                    236:                           ,uint retries, uint wait_secs
                    237:                           ,const char* prot
                    238:                           ,int (*lprintf)(int level, char *fmt, ...))
                    239: {
                    240:        char    port_str[128];
                    241:        int             result=-1;
                    242:        uint    i;
                    243: 
                    244:        if(addr->sa_family==AF_INET)
                    245:                SAFEPRINTF(port_str," to port %u",ntohs(((SOCKADDR_IN *)(addr))->sin_port)); 
                    246:        else
                    247:                port_str[0]=0;
                    248:        for(i=0;i<=retries;i++) {
                    249:                if((result=bind(s,addr,addrlen))==0)
                    250:                        break;
                    251:                if(lprintf!=NULL)
                    252:                        lprintf(i<retries ? LOG_WARNING:LOG_ERR
                    253:                                ,"%04d !ERROR %d binding %s socket%s", s, ERROR_VALUE, prot, port_str);
                    254:                if(i<retries) {
                    255:                        if(lprintf!=NULL)
                    256:                                lprintf(LOG_WARNING,"%04d Will retry in %u seconds (%u of %u)"
                    257:                                        ,s, wait_secs, i+1, retries);
                    258:                        SLEEP(wait_secs*1000);
                    259:                }
                    260:        }
                    261:        return(result);
                    262: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.