/[resiprocate]/main/rutil/Socket.cxx
ViewVC logotype

Contents of /main/rutil/Socket.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11235 - (show annotations) (download)
Mon Sep 15 17:20:11 2014 UTC (5 years, 2 months ago) by dpocock
File MIME type: text/plain
File size: 8992 byte(s)
resip/stack: TcpBaseTransport: generalize support for SO_NOSIGPIPE
1
2 #include <cassert>
3 #include <fcntl.h>
4 #include <errno.h>
5
6 #include "rutil/compat.hxx"
7 #include "rutil/Socket.hxx"
8 #include "rutil/Logger.hxx"
9
10 #ifndef WIN32
11 #include <unistd.h>
12 #include <sys/resource.h> // for getrlimit()
13 #endif
14
15 using namespace resip;
16 using namespace std;
17
18 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
19
20 bool
21 resip::makeSocketNonBlocking(Socket fd)
22 {
23 #if defined(WIN32)
24 unsigned long noBlock = 1;
25 int errNoBlock = ioctlsocket( fd, FIONBIO , &noBlock );
26 if ( errNoBlock != 0 )
27 {
28 return false;
29 }
30 #else
31 int flags = fcntl( fd, F_GETFL, 0);
32 int errNoBlock = fcntl(fd, F_SETFL, flags | O_NONBLOCK );
33 if ( errNoBlock != 0 ) // !cj! I may have messed up this line
34 {
35 return false;
36 }
37 #endif
38 return true;
39 }
40
41
42 bool
43 resip::makeSocketBlocking(Socket fd)
44 {
45 #if defined(WIN32)
46 unsigned long noBlock = 0;
47 int errNoBlock = ioctlsocket( fd, FIONBIO , &noBlock );
48 if ( errNoBlock != 0 )
49 {
50 return false;
51 }
52 #else
53 int flags = fcntl( fd, F_GETFL, 0);
54 int errNoBlock = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK );
55 if ( errNoBlock != 0 ) // !cj! I may have messed up this line
56 {
57 return false;
58 }
59 #endif
60 return true;
61 }
62
63
64
65 bool
66 configureConnectedSocket(Socket fd)
67 {
68 #ifdef REQUIRE_SO_NOSIGPIPE
69 int on = 1;
70 if ( ::setsockopt ( fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&on, sizeof(on)) )
71 {
72 int e = getErrno();
73 ErrorLog (<< "Couldn't set sockoption SO_NOSIGPIPE: " << strerror(e));
74 error(e);
75 return false;
76 }
77 #endif
78 return true;
79 }
80
81
82
83 void
84 resip::initNetwork()
85 {
86 #if defined(WIN32)
87 bool doneInit=false;
88 if( !doneInit )
89 {
90 doneInit=true;
91
92 WORD wVersionRequested = MAKEWORD( 2, 2 );
93 WSADATA wsaData;
94 int err;
95
96 err = WSAStartup( wVersionRequested, &wsaData );
97 if ( err != 0 )
98 {
99 // could not find a usable WinSock DLL
100 //cerr << "Could not load winsock" << endl;
101 assert(0); // is this is failing, try a different version that 2.2, 1.0 or later will likely work
102 exit(1);
103 }
104
105 /* Confirm that the WinSock DLL supports 2.2.*/
106 /* Note that if the DLL supports versions greater */
107 /* than 2.2 in addition to 2.2, it will still return */
108 /* 2.2 in wVersion since that is the version we */
109 /* requested. */
110
111 if ( LOBYTE( wsaData.wVersion ) != 2 ||
112 HIBYTE( wsaData.wVersion ) != 2 )
113 {
114 /* Tell the user that we could not find a usable */
115 /* WinSock DLL. */
116 WSACleanup( );
117 //cerr << "Bad winsock verion" << endl;
118 // TODO !cj! - add error message logging
119 assert(0); // if this is failing, try a different version that 2.2, 1.0 or later will likely work
120 exit(1);
121 }
122 }
123 #endif
124 }
125
126
127 #if defined(WIN32)
128 int
129 resip::closeSocket( Socket fd )
130 {
131 return closesocket(fd);
132 }
133 #else
134 int
135 resip::closeSocket( Socket fd )
136 {
137 //int ret = ::shutdown(fd, SHUT_RDWR); !jf!
138 int ret = ::close(fd);
139 if (ret < 0)
140 {
141 InfoLog (<< "Failed to shutdown socket " << fd << " : " << strerror(errno));
142 }
143 return ret;
144 }
145 #endif
146
147 // code moved from resip/stack/ConnectionManager.cxx
148 // appears to work on both linux and windows
149 int resip::getSocketError(Socket fd)
150 {
151 int errNum = 0;
152 int errNumSize = sizeof(errNum);
153 getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&errNum, (socklen_t *)&errNumSize);
154 /// XXX: should check return code of getsockopt
155 return errNum;
156 }
157
158 /**
159 Returns negative on error, or number of (positive) allowed fds
160 **/
161 int
162 resip::increaseLimitFds(unsigned int targetFds)
163 {
164 #if defined(WIN32)
165 // kw: i don't know if any equiv on windows
166 return targetFds;
167 #else
168 struct rlimit lim;
169
170 if (getrlimit(RLIMIT_NOFILE, &lim) < 0)
171 {
172 CritLog(<<"getrlimit(NOFILE) failed: " << strerror(errno));
173 return -1;
174 }
175 if (lim.rlim_cur==RLIM_INFINITY || targetFds < lim.rlim_cur)
176 {
177 return targetFds;
178 }
179
180 int euid = geteuid();
181 if (lim.rlim_max==RLIM_INFINITY || targetFds < lim.rlim_max)
182 {
183 lim.rlim_cur=targetFds;
184 }
185 else
186 {
187 if (euid!=0)
188 {
189 CritLog(<<"Attempting to increase number of fds when not root. This probably wont work");
190 }
191 lim.rlim_cur=targetFds;
192 lim.rlim_max=targetFds;
193 }
194
195 if (setrlimit(RLIMIT_NOFILE, &lim) < 0)
196 {
197 CritLog(<<"setrlimit(NOFILE)=(c="<<lim.rlim_cur<<",m="<<lim.rlim_max
198 <<",uid="<<euid<<") failed: " << strerror(errno));
199 /* There is intermediate: could raise cur to max */
200 return -1;
201 }
202 return targetFds;
203 #endif
204 }
205
206 /**
207 Some OSs (Linux in particular) silently ignore requests to set
208 too big and do not return an error code. Thus we always check.
209 Also, the returned value (getsockopt) can be larger than the requested
210 value (kernel internally doubles).
211 manpage says sockopt uses integer as data-type
212 If {buflen} is negative, we skip the set and just read
213 Return the get size or -1 if the set didn't work
214 **/
215 static int trySetRcvBuf(Socket fd, int buflen)
216 {
217 if (buflen > 0)
218 {
219 int wbuflen = buflen;
220 #if !defined(WIN32)
221 if (::setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &wbuflen, sizeof(wbuflen)) == -1)
222 #else
223 if (::setsockopt (fd, SOL_SOCKET, SO_RCVBUF, (const char*)&wbuflen, sizeof(wbuflen)) == -1)
224 #endif
225 {
226 return -1;
227 }
228 }
229 int rbuflen = 0;
230 unsigned optlen = sizeof(rbuflen);
231 if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&rbuflen, (socklen_t *)&optlen) == -1)
232 {
233 return -1;
234 }
235 assert(optlen == sizeof(rbuflen));
236 if (rbuflen < buflen)
237 {
238 return -1;
239 }
240 return rbuflen;
241 }
242
243 /**
244 **/
245 int resip::setSocketRcvBufLen(Socket fd, int buflen)
246 {
247 assert(buflen >= 1024);
248 int goal=buflen;
249 int trylen=goal;
250 int sts;
251 int lastgoodset = 0, lastgoodget=0;
252
253 /* go down by factors of 2 */
254 for (; ; trylen /= 2)
255 {
256 if (trylen < 1024)
257 {
258 ErrLog(<<"setsockopt(SO_RCVBUF) failed");
259 return -1;
260 }
261 if ((sts=trySetRcvBuf(fd, trylen)) >= 0)
262 {
263 lastgoodset = trylen;
264 lastgoodget = sts;
265 break;
266 }
267 }
268
269 /* go up by 10% steps */
270 unsigned step = trylen/10;
271 for ( ; trylen<goal; trylen+=step)
272 {
273 if ((sts=trySetRcvBuf(fd,trylen)) < 0)
274 {
275 break;
276 }
277 lastgoodset = trylen;
278 lastgoodget = sts;
279 }
280 if (lastgoodset < goal)
281 {
282 ErrLog(<<"setsockopt(SO_RCVBUF) goal "<<goal<<" not met (set="
283 <<lastgoodset<<",get="<<lastgoodget<<")");
284 }
285 else
286 {
287 InfoLog(<<"setsockopt(SO_RCVBUF) goal "<<goal<<" met (set="
288 <<lastgoodset<<",get="<<lastgoodget<<")");
289 }
290 return lastgoodset;
291 }
292
293
294 /* ====================================================================
295 * The Vovida Software License, Version 1.0
296 *
297 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
298 *
299 * Redistribution and use in source and binary forms, with or without
300 * modification, are permitted provided that the following conditions
301 * are met:
302 *
303 * 1. Redistributions of source code must retain the above copyright
304 * notice, this list of conditions and the following disclaimer.
305 *
306 * 2. Redistributions in binary form must reproduce the above copyright
307 * notice, this list of conditions and the following disclaimer in
308 * the documentation and/or other materials provided with the
309 * distribution.
310 *
311 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
312 * and "Vovida Open Communication Application Library (VOCAL)" must
313 * not be used to endorse or promote products derived from this
314 * software without prior written permission. For written
315 * permission, please contact vocal@vovida.org.
316 *
317 * 4. Products derived from this software may not be called "VOCAL", nor
318 * may "VOCAL" appear in their name, without prior written
319 * permission of Vovida Networks, Inc.
320 *
321 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
322 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
323 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
324 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
325 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
326 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
327 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
328 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
329 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
330 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
331 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
332 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
333 * DAMAGE.
334 *
335 * ====================================================================
336 *
337 * This software consists of voluntary contributions made by Vovida
338 * Networks, Inc. and many individuals on behalf of Vovida Networks,
339 * Inc. For more information on Vovida Networks, Inc., please see
340 * <http://www.vovida.org/>.
341 *
342 */

Properties

Name Value
svn:eol-style native
svn:mime-type text/plain

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27