Coverage Report

Created: 2025-10-12 06:48

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