|
reSIProcate/rutil
9694
|
00001 00002 #include <cassert> 00003 #include <fcntl.h> 00004 #include <errno.h> 00005 00006 #include "rutil/compat.hxx" 00007 #include "rutil/Socket.hxx" 00008 #include "rutil/Logger.hxx" 00009 00010 #ifndef WIN32 00011 #include <unistd.h> 00012 #include <sys/resource.h> // for getrlimit() 00013 #endif 00014 00015 using namespace resip; 00016 using namespace std; 00017 00018 #define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT 00019 00020 bool 00021 resip::makeSocketNonBlocking(Socket fd) 00022 { 00023 #if defined(WIN32) 00024 unsigned long noBlock = 1; 00025 int errNoBlock = ioctlsocket( fd, FIONBIO , &noBlock ); 00026 if ( errNoBlock != 0 ) 00027 { 00028 return false; 00029 } 00030 #else 00031 int flags = fcntl( fd, F_GETFL, 0); 00032 int errNoBlock = fcntl(fd, F_SETFL, flags | O_NONBLOCK ); 00033 if ( errNoBlock != 0 ) // !cj! I may have messed up this line 00034 { 00035 return false; 00036 } 00037 #endif 00038 return true; 00039 } 00040 00041 00042 bool 00043 resip::makeSocketBlocking(Socket fd) 00044 { 00045 #if defined(WIN32) 00046 unsigned long noBlock = 0; 00047 int errNoBlock = ioctlsocket( fd, FIONBIO , &noBlock ); 00048 if ( errNoBlock != 0 ) 00049 { 00050 return false; 00051 } 00052 #else 00053 int flags = fcntl( fd, F_GETFL, 0); 00054 int errNoBlock = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK ); 00055 if ( errNoBlock != 0 ) // !cj! I may have messed up this line 00056 { 00057 return false; 00058 } 00059 #endif 00060 return true; 00061 } 00062 00063 00064 00065 void 00066 resip::initNetwork() 00067 { 00068 #if defined(WIN32) 00069 bool doneInit=false; 00070 if( !doneInit ) 00071 { 00072 doneInit=true; 00073 00074 WORD wVersionRequested = MAKEWORD( 2, 2 ); 00075 WSADATA wsaData; 00076 int err; 00077 00078 err = WSAStartup( wVersionRequested, &wsaData ); 00079 if ( err != 0 ) 00080 { 00081 // could not find a usable WinSock DLL 00082 //cerr << "Could not load winsock" << endl; 00083 assert(0); // is this is failing, try a different version that 2.2, 1.0 or later will likely work 00084 exit(1); 00085 } 00086 00087 /* Confirm that the WinSock DLL supports 2.2.*/ 00088 /* Note that if the DLL supports versions greater */ 00089 /* than 2.2 in addition to 2.2, it will still return */ 00090 /* 2.2 in wVersion since that is the version we */ 00091 /* requested. */ 00092 00093 if ( LOBYTE( wsaData.wVersion ) != 2 || 00094 HIBYTE( wsaData.wVersion ) != 2 ) 00095 { 00096 /* Tell the user that we could not find a usable */ 00097 /* WinSock DLL. */ 00098 WSACleanup( ); 00099 //cerr << "Bad winsock verion" << endl; 00100 // TODO !cj! - add error message logging 00101 assert(0); // if this is failing, try a different version that 2.2, 1.0 or later will likely work 00102 exit(1); 00103 } 00104 } 00105 #endif 00106 } 00107 00108 00109 #if defined(WIN32) 00110 int 00111 resip::closeSocket( Socket fd ) 00112 { 00113 return closesocket(fd); 00114 } 00115 #else 00116 int 00117 resip::closeSocket( Socket fd ) 00118 { 00119 //int ret = ::shutdown(fd, SHUT_RDWR); !jf! 00120 int ret = ::close(fd); 00121 if (ret < 0) 00122 { 00123 InfoLog (<< "Failed to shutdown socket " << fd << " : " << strerror(errno)); 00124 } 00125 return ret; 00126 } 00127 #endif 00128 00129 // code moved from resip/stack/ConnectionManager.cxx 00130 // appears to work on both linux and windows 00131 int resip::getSocketError(Socket fd) 00132 { 00133 int errNum = 0; 00134 int errNumSize = sizeof(errNum); 00135 getsockopt(fd, SOL_SOCKET, SO_ERROR, 00136 (char *)&errNum, (socklen_t *)&errNumSize); 00138 return errNum; 00139 } 00140 00144 int 00145 resip::increaseLimitFds(unsigned int targetFds) 00146 { 00147 #if defined(WIN32) 00148 // kw: i don't know if any equiv on windows 00149 return targetFds; 00150 #else 00151 struct rlimit lim; 00152 00153 if (getrlimit(RLIMIT_NOFILE, &lim) < 0) 00154 { 00155 CritLog(<<"getrlimit(NOFILE) failed: " << strerror(errno)); 00156 return -1; 00157 } 00158 if (lim.rlim_cur==RLIM_INFINITY || targetFds < lim.rlim_cur) 00159 { 00160 return targetFds; 00161 } 00162 00163 int euid = geteuid(); 00164 if (lim.rlim_max==RLIM_INFINITY || targetFds < lim.rlim_max) 00165 { 00166 lim.rlim_cur=targetFds; 00167 } 00168 else 00169 { 00170 if (euid!=0) 00171 { 00172 CritLog(<<"Attempting to increase number of fds when not root. This probably wont work"); 00173 } 00174 lim.rlim_cur=targetFds; 00175 lim.rlim_max=targetFds; 00176 } 00177 00178 if (setrlimit(RLIMIT_NOFILE, &lim) < 0) 00179 { 00180 CritLog(<<"setrlimit(NOFILE)=(c="<<lim.rlim_cur<<",m="<<lim.rlim_max 00181 <<",uid="<<euid<<") failed: " << strerror(errno)); 00182 /* There is intermediate: could raise cur to max */ 00183 return -1; 00184 } 00185 return targetFds; 00186 #endif 00187 } 00188 00198 static int trySetRcvBuf(Socket fd, int buflen) 00199 { 00200 if (buflen > 0) 00201 { 00202 int wbuflen = buflen; 00203 #if !defined(WIN32) 00204 if (::setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &wbuflen, sizeof(wbuflen)) == -1) 00205 #else 00206 if (::setsockopt (fd, SOL_SOCKET, SO_RCVBUF, (const char*)&wbuflen, sizeof(wbuflen)) == -1) 00207 #endif 00208 { 00209 return -1; 00210 } 00211 } 00212 int rbuflen = 0; 00213 unsigned optlen = sizeof(rbuflen); 00214 if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&rbuflen, (socklen_t *)&optlen) == -1) 00215 { 00216 return -1; 00217 } 00218 assert(optlen == sizeof(rbuflen)); 00219 if (rbuflen < buflen) 00220 { 00221 return -1; 00222 } 00223 return rbuflen; 00224 } 00225 00228 int resip::setSocketRcvBufLen(Socket fd, int buflen) 00229 { 00230 assert(buflen >= 1024); 00231 int goal=buflen; 00232 int trylen=goal; 00233 int sts; 00234 int lastgoodset = 0, lastgoodget=0; 00235 00236 /* go down by factors of 2 */ 00237 for (; ; trylen /= 2) 00238 { 00239 if (trylen < 1024) 00240 { 00241 ErrLog(<<"setsockopt(SO_RCVBUF) failed"); 00242 return -1; 00243 } 00244 if ((sts=trySetRcvBuf(fd, trylen)) >= 0) 00245 { 00246 lastgoodset = trylen; 00247 lastgoodget = sts; 00248 break; 00249 } 00250 } 00251 00252 /* go up by 10% steps */ 00253 unsigned step = trylen/10; 00254 for ( ; trylen<goal; trylen+=step) 00255 { 00256 if ((sts=trySetRcvBuf(fd,trylen)) < 0) 00257 { 00258 break; 00259 } 00260 lastgoodset = trylen; 00261 lastgoodget = sts; 00262 } 00263 if (lastgoodset < goal) 00264 { 00265 ErrLog(<<"setsockopt(SO_RCVBUF) goal "<<goal<<" not met (set=" 00266 <<lastgoodset<<",get="<<lastgoodget<<")"); 00267 } 00268 else 00269 { 00270 InfoLog(<<"setsockopt(SO_RCVBUF) goal "<<goal<<" met (set=" 00271 <<lastgoodset<<",get="<<lastgoodget<<")"); 00272 } 00273 return lastgoodset; 00274 } 00275 00276 00277 /* ==================================================================== 00278 * The Vovida Software License, Version 1.0 00279 * 00280 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00281 * 00282 * Redistribution and use in source and binary forms, with or without 00283 * modification, are permitted provided that the following conditions 00284 * are met: 00285 * 00286 * 1. Redistributions of source code must retain the above copyright 00287 * notice, this list of conditions and the following disclaimer. 00288 * 00289 * 2. Redistributions in binary form must reproduce the above copyright 00290 * notice, this list of conditions and the following disclaimer in 00291 * the documentation and/or other materials provided with the 00292 * distribution. 00293 * 00294 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00295 * and "Vovida Open Communication Application Library (VOCAL)" must 00296 * not be used to endorse or promote products derived from this 00297 * software without prior written permission. For written 00298 * permission, please contact vocal@vovida.org. 00299 * 00300 * 4. Products derived from this software may not be called "VOCAL", nor 00301 * may "VOCAL" appear in their name, without prior written 00302 * permission of Vovida Networks, Inc. 00303 * 00304 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00305 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00306 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00307 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00308 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00309 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00310 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00311 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00312 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00313 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00314 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00315 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00316 * DAMAGE. 00317 * 00318 * ==================================================================== 00319 * 00320 * This software consists of voluntary contributions made by Vovida 00321 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00322 * Inc. For more information on Vovida Networks, Inc., please see 00323 * <http://www.vovida.org/>. 00324 * 00325 */
1.7.5.1