|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.