|
|
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.