groupsock/GroupsockHelper.cpp File Reference

#include "GroupsockHelper.hh"
#include <stdarg.h>
#include <time.h>
#include <fcntl.h>
#include <stdio.h>

Include dependency graph for GroupsockHelper.cpp:

Go to the source code of this file.

Data Structures

struct  ip_mreq_source

Defines

#define initializeWinsockIfNecessary()   1
#define TTL_TYPE   u_int8_t
#define IP_ADD_SOURCE_MEMBERSHIP   25
#define IP_DROP_SOURCE_MEMBERSHIP   26

Functions

static void socketErr (UsageEnvironment &env, char *errorMsg)
int setupDatagramSocket (UsageEnvironment &env, Port port, Boolean)
Boolean makeSocketNonBlocking (int sock)
int setupStreamSocket (UsageEnvironment &env, Port port, Boolean makeNonBlocking)
static int blockUntilReadable (UsageEnvironment &env, int socket, struct timeval *timeout)
int readSocket (UsageEnvironment &env, int socket, unsigned char *buffer, unsigned bufferSize, struct sockaddr_in &fromAddress, struct timeval *timeout)
int readSocketExact (UsageEnvironment &env, int socket, unsigned char *buffer, unsigned bufferSize, struct sockaddr_in &fromAddress, struct timeval *timeout)
Boolean writeSocket (UsageEnvironment &env, int socket, struct in_addr address, Port port, u_int8_t ttlArg, unsigned char *buffer, unsigned bufferSize)
static unsigned getBufferSize (UsageEnvironment &env, int bufOptName, int socket)
unsigned getSendBufferSize (UsageEnvironment &env, int socket)
unsigned getReceiveBufferSize (UsageEnvironment &env, int socket)
static unsigned setBufferTo (UsageEnvironment &env, int bufOptName, int socket, unsigned requestedSize)
unsigned setSendBufferTo (UsageEnvironment &env, int socket, unsigned requestedSize)
unsigned setReceiveBufferTo (UsageEnvironment &env, int socket, unsigned requestedSize)
static unsigned increaseBufferTo (UsageEnvironment &env, int bufOptName, int socket, unsigned requestedSize)
unsigned increaseSendBufferTo (UsageEnvironment &env, int socket, unsigned requestedSize)
unsigned increaseReceiveBufferTo (UsageEnvironment &env, int socket, unsigned requestedSize)
Boolean socketJoinGroup (UsageEnvironment &env, int socket, netAddressBits groupAddress)
Boolean socketLeaveGroup (UsageEnvironment &, int socket, netAddressBits groupAddress)
Boolean socketJoinGroupSSM (UsageEnvironment &env, int socket, netAddressBits groupAddress, netAddressBits sourceFilterAddr)
Boolean socketLeaveGroupSSM (UsageEnvironment &, int socket, netAddressBits groupAddress, netAddressBits sourceFilterAddr)
static Boolean getSourcePort0 (int socket, portNumBits &resultPortNum)
Boolean getSourcePort (UsageEnvironment &env, int socket, Port &port)
static Boolean badAddress (netAddressBits addr)
netAddressBits ourIPAddress (UsageEnvironment &env)
netAddressBits chooseRandomIPv4SSMAddress (UsageEnvironment &env)
char const * timestampString ()

Variables

netAddressBits SendingInterfaceAddr = INADDR_ANY
netAddressBits ReceivingInterfaceAddr = INADDR_ANY
static int reuseFlag = 1
Boolean loopbackWorks = 1


Define Documentation

 
#define initializeWinsockIfNecessary (  )     1

Definition at line 30 of file GroupsockHelper.cpp.

Referenced by BasicUsageEnvironment::BasicUsageEnvironment(), our_gethostbyname(), setupDatagramSocket(), and setupStreamSocket().

#define IP_ADD_SOURCE_MEMBERSHIP   25

Definition at line 490 of file GroupsockHelper.cpp.

Referenced by socketJoinGroupSSM().

#define IP_DROP_SOURCE_MEMBERSHIP   26

Definition at line 491 of file GroupsockHelper.cpp.

Referenced by socketLeaveGroupSSM().

#define TTL_TYPE   u_int8_t

Referenced by writeSocket().


Function Documentation

static Boolean badAddress ( netAddressBits  addr  )  [static]

Definition at line 557 of file GroupsockHelper.cpp.

Referenced by ourIPAddress().

00557                                                {
00558   // Check for some possible erroneous addresses:
00559   netAddressBits hAddr = ntohl(addr);
00560   return (hAddr == 0x7F000001 /* 127.0.0.1 */
00561           || hAddr == 0
00562           || hAddr == (netAddressBits)(~0));
00563 }

static int blockUntilReadable ( UsageEnvironment env,
int  socket,
struct timeval *  timeout 
) [static]

Definition at line 219 of file GroupsockHelper.cpp.

References env, NULL, and socketErr().

Referenced by readSocket().

00220                                                                    {
00221   int result = -1;
00222   do {
00223     fd_set rd_set;
00224     FD_ZERO(&rd_set);
00225     if (socket < 0) break;
00226     FD_SET((unsigned) socket, &rd_set);
00227     const unsigned numFds = socket+1;
00228     
00229     result = select(numFds, &rd_set, NULL, NULL, timeout);
00230     if (timeout != NULL && result == 0) {
00231       break; // this is OK - timeout occurred
00232     } else if (result <= 0) {
00233 #if defined(__WIN32__) || defined(_WIN32)
00234 #else
00235       if (errno == EINTR || errno == EAGAIN) continue;
00236 #endif
00237       socketErr(env, "select() error: ");
00238       break;
00239     }
00240     
00241     if (!FD_ISSET(socket, &rd_set)) {
00242       socketErr(env, "select() error - !FD_ISSET");
00243       break;
00244     }
00245   } while (0);
00246 
00247   return result;
00248 }

netAddressBits chooseRandomIPv4SSMAddress ( UsageEnvironment env  ) 

Definition at line 688 of file GroupsockHelper.cpp.

References env, our_random(), and ourIPAddress().

Referenced by main().

00688                                                                  {
00689   // First, a hack to ensure that our random number generator is seeded:
00690   (void) ourIPAddress(env);
00691 
00692   // Choose a random address in the range [232.0.1.0, 232.255.255.255)
00693   // i.e., [0xE8000100, 0xE8FFFFFF)
00694   netAddressBits const first = 0xE8000100, lastPlus1 = 0xE8FFFFFF;
00695   netAddressBits const range = lastPlus1 - first;
00696 
00697   return htonl(first + ((netAddressBits)our_random())%range);
00698 }

static unsigned getBufferSize ( UsageEnvironment env,
int  bufOptName,
int  socket 
) [static]

Definition at line 360 of file GroupsockHelper.cpp.

References env, socketErr(), and SOCKLEN_T.

Referenced by getReceiveBufferSize(), getSendBufferSize(), increaseBufferTo(), and setBufferTo().

00361                                           {
00362   unsigned curSize;
00363   SOCKLEN_T sizeSize = sizeof curSize;
00364   if (getsockopt(socket, SOL_SOCKET, bufOptName,
00365                  (char*)&curSize, &sizeSize) < 0) {
00366     socketErr(env, "getBufferSize() error: ");
00367     return 0;
00368   }
00369 
00370   return curSize;
00371 }

unsigned getReceiveBufferSize ( UsageEnvironment env,
int  socket 
)

Definition at line 375 of file GroupsockHelper.cpp.

References env, and getBufferSize().

Referenced by main().

00375                                                                  {
00376   return getBufferSize(env, SO_RCVBUF, socket);
00377 }

unsigned getSendBufferSize ( UsageEnvironment env,
int  socket 
)

Definition at line 372 of file GroupsockHelper.cpp.

References env, and getBufferSize().

00372                                                               {
00373   return getBufferSize(env, SO_SNDBUF, socket);
00374 }

Boolean getSourcePort ( UsageEnvironment env,
int  socket,
Port port 
)

Definition at line 540 of file GroupsockHelper.cpp.

References env, False, getSourcePort0(), MAKE_SOCKADDR_IN, socketErr(), and True.

Referenced by MediaSubsession::initiate(), RTSPServer::setUpOurSocket(), RTSPOverHTTPServer::setUpOurSocket(), HTTPSink::setUpOurSocket(), SIPClient::SIPClient(), and OutputSocket::write().

00540                                                                      {
00541   portNumBits portNum = 0;
00542   if (!getSourcePort0(socket, portNum) || portNum == 0) {
00543     // Hack - call bind(), then try again:
00544     MAKE_SOCKADDR_IN(name, INADDR_ANY, 0);
00545     bind(socket, (struct sockaddr*)&name, sizeof name);
00546 
00547     if (!getSourcePort0(socket, portNum) || portNum == 0) {
00548       socketErr(env, "getsockname() error: ");
00549       return False;
00550     }
00551   }
00552   
00553   port = Port(portNum);
00554   return True;
00555 }

static Boolean getSourcePort0 ( int  socket,
portNumBits resultPortNum 
) [static]

Definition at line 531 of file GroupsockHelper.cpp.

References False, SOCKLEN_T, and True.

Referenced by getSourcePort().

00531                                                                                     {
00532   sockaddr_in test; test.sin_port = 0;
00533   SOCKLEN_T len = sizeof test;
00534   if (getsockname(socket, (struct sockaddr*)&test, &len) < 0) return False;
00535   
00536   resultPortNum = ntohs(test.sin_port);
00537   return True;
00538 }

static unsigned increaseBufferTo ( UsageEnvironment env,
int  bufOptName,
int  socket,
unsigned  requestedSize 
) [static]

Definition at line 396 of file GroupsockHelper.cpp.

References env, getBufferSize(), and SOCKLEN_T.

Referenced by increaseReceiveBufferTo(), and increaseSendBufferTo().

00397                                                                      {
00398   // First, get the current buffer size.  If it's already at least
00399   // as big as what we're requesting, do nothing.
00400   unsigned curSize = getBufferSize(env, bufOptName, socket);
00401 
00402   // Next, try to increase the buffer to the requested size,
00403   // or to some smaller size, if that's not possible:
00404   while (requestedSize > curSize) {
00405     SOCKLEN_T sizeSize = sizeof requestedSize;
00406     if (setsockopt(socket, SOL_SOCKET, bufOptName,
00407                    (char*)&requestedSize, sizeSize) >= 0) {
00408       // success
00409       return requestedSize;
00410     }
00411     requestedSize = (requestedSize+curSize)/2;
00412   }
00413 
00414   return getBufferSize(env, bufOptName, socket);
00415 }

unsigned increaseReceiveBufferTo ( UsageEnvironment env,
int  socket,
unsigned  requestedSize 
)

Definition at line 420 of file GroupsockHelper.cpp.

References env, and increaseBufferTo().

Referenced by BasicUDPSource::BasicUDPSource(), MP3HTTPSource::createNew(), and MultiFramedRTPSource::MultiFramedRTPSource().

00421                                                                      {
00422   return increaseBufferTo(env, SO_RCVBUF, socket, requestedSize);
00423 }

unsigned increaseSendBufferTo ( UsageEnvironment env,
int  socket,
unsigned  requestedSize 
)

Definition at line 416 of file GroupsockHelper.cpp.

References env, and increaseBufferTo().

Referenced by RTSPServer::incomingConnectionHandler1(), RTSPOverHTTPServer::incomingConnectionHandler1(), RTPInterface::RTPInterface(), DarwinInjector::setDestination(), RTSPServer::setUpOurSocket(), RTSPOverHTTPServer::setUpOurSocket(), and HTTPSink::setUpOurSocket().

00417                                                                   {
00418   return increaseBufferTo(env, SO_SNDBUF, socket, requestedSize);
00419 }

Boolean makeSocketNonBlocking ( int  sock  ) 

Definition at line 137 of file GroupsockHelper.cpp.

Referenced by BasicUDPSource::BasicUDPSource(), RTSPServer::incomingConnectionHandler1(), RTSPOverHTTPServer::incomingConnectionHandler1(), RTPInterface::RTPInterface(), and setupStreamSocket().

00137                                         {
00138 #if defined(__WIN32__) || defined(_WIN32) || defined(IMN_PIM)
00139   unsigned long arg = 1;
00140   return ioctlsocket(sock, FIONBIO, &arg) == 0;
00141 #elif defined(VXWORKS)
00142   int arg = 1;
00143   return ioctl(sock, FIONBIO, (int)&arg) == 0;
00144 #else
00145   int curFlags = fcntl(sock, F_GETFL, 0);
00146   return fcntl(sock, F_SETFL, curFlags|O_NONBLOCK) >= 0;
00147 #endif
00148 }

netAddressBits ourIPAddress ( UsageEnvironment env  ) 

Definition at line 567 of file GroupsockHelper.cpp.

References badAddress(), closeSocket, env, if(), loopbackWorks, NULL, our_inet_addr(), our_srandom(), readSocket(), UsageEnvironment::setResultErrMsg(), UsageEnvironment::setResultMsg(), setupDatagramSocket(), socketJoinGroup(), socketLeaveGroup(), and writeSocket().

Referenced by chooseRandomIPv4SSMAddress(), ServerMediaSession::generateSDPDescription(), Groupsock::Groupsock(), Groupsock::output(), RTSPServer::rtspURLPrefix(), SIPClient::SIPClient(), and Groupsock::wasLoopedBackFromUs().

00567                                                    {
00568   static netAddressBits ourAddress = 0;
00569   int sock = -1;
00570   struct in_addr testAddr;
00571   
00572   if (ourAddress == 0) {
00573     // We need to find our source address
00574     struct sockaddr_in fromAddr;
00575     fromAddr.sin_addr.s_addr = 0;
00576     
00577     // Get our address by sending a (0-TTL) multicast packet,
00578     // receiving it, and looking at the source address used.
00579     // (This is kinda bogus, but it provides the best guarantee
00580     // that other nodes will think our address is the same as we do.)
00581     do {
00582       loopbackWorks = 0; // until we learn otherwise
00583 
00584       testAddr.s_addr = our_inet_addr("228.67.43.91"); // arbitrary
00585       Port testPort(15947); // ditto
00586       
00587       sock = setupDatagramSocket(env, testPort);
00588       if (sock < 0) break;
00589       
00590       if (!socketJoinGroup(env, sock, testAddr.s_addr)) break;
00591       
00592       unsigned char testString[] = "hostIdTest";
00593       unsigned testStringLength = sizeof testString;
00594       
00595       if (!writeSocket(env, sock, testAddr, testPort, 0,
00596                        testString, testStringLength)) break;
00597       
00598       unsigned char readBuffer[20];
00599       struct timeval timeout;
00600       timeout.tv_sec = 5;
00601       timeout.tv_usec = 0;
00602       int bytesRead = readSocket(env, sock,
00603                                  readBuffer, sizeof readBuffer,
00604                                  fromAddr, &timeout);
00605       if (bytesRead == 0 // timeout occurred
00606           || bytesRead != (int)testStringLength
00607           || strncmp((char*)readBuffer, (char*)testString,
00608                      testStringLength) != 0) {
00609         break;
00610       }
00611 
00612       loopbackWorks = 1;
00613     } while (0);
00614 
00615     if (!loopbackWorks) do {
00616       // We couldn't find our address using multicast loopback
00617       // so try instead to look it up directly.
00618       char hostname[100];
00619       hostname[0] = '\0';
00620 #ifndef CRIS
00621       gethostname(hostname, sizeof hostname);
00622 #endif
00623       if (hostname[0] == '\0') {
00624         env.setResultErrMsg("initial gethostname() failed");
00625         break;
00626       }
00627       
00628 #if defined(VXWORKS)
00629 #include <hostLib.h>
00630       if (ERROR == (ourAddress = hostGetByName( hostname ))) break;
00631 #else
00632       struct hostent* hstent
00633         = (struct hostent*)gethostbyname(hostname);
00634       if (hstent == NULL || hstent->h_length != 4) {
00635         env.setResultErrMsg("initial gethostbyname() failed");
00636         break;
00637       }
00638       // Take the first address that's not bad
00639       // (This code, like many others, won't handle IPv6)
00640       netAddressBits addr = 0;
00641       for (unsigned i = 0; ; ++i) {
00642         char* addrPtr = hstent->h_addr_list[i];
00643         if (addrPtr == NULL) break;
00644         
00645         netAddressBits a = *(netAddressBits*)addrPtr;
00646         if (!badAddress(a)) {
00647           addr = a;
00648           break;
00649         }
00650       }
00651       if (addr != 0) {
00652         fromAddr.sin_addr.s_addr = addr;
00653       } else {
00654         env.setResultMsg("no address");
00655         break;
00656       }
00657     } while (0);
00658     
00659     // Make sure we have a good address:
00660     netAddressBits from = fromAddr.sin_addr.s_addr;
00661     if (badAddress(from)) {
00662       char tmp[100];
00663       sprintf(tmp,
00664               "This computer has an invalid IP address: 0x%x",
00665               (netAddressBits)(ntohl(from)));
00666       env.setResultMsg(tmp);
00667       from = 0;
00668     }
00669     
00670     ourAddress = from;
00671 #endif
00672     
00673     if (sock >= 0) {
00674       socketLeaveGroup(env, sock, testAddr.s_addr);
00675       closeSocket(sock);
00676     }
00677     
00678     // Use our newly-discovered IP address, and the current time,
00679     // to initialize the random number generator's seed:
00680     struct timeval timeNow;
00681     gettimeofday(&timeNow, NULL);
00682     unsigned seed = ourAddress^timeNow.tv_sec^timeNow.tv_usec;
00683     our_srandom(seed);
00684   }
00685   return ourAddress;
00686 }

int readSocket ( UsageEnvironment env,
int  socket,
unsigned char *  buffer,
unsigned  bufferSize,
struct sockaddr_in &  fromAddress,
struct timeval *  timeout 
)

Definition at line 254 of file GroupsockHelper.cpp.

References blockUntilReadable(), env, UsageEnvironment::getErrno(), NULL, socketErr(), and SOCKLEN_T.

Referenced by RTSPClient::describeURL(), RTSPClient::getMediaSessionParameter(), RTSPClient::getResponse1(), RTPInterface::handleRead(), Groupsock::handleRead(), RTSPServer::RTSPClientSession::incomingRequestHandler1(), RTSPOverHTTPServer::HTTPClientConnection::incomingRequestHandler1(), ourIPAddress(), readSocketExact(), and SocketDescriptor::tcpReadHandler().

00257                                         {
00258   int bytesRead = -1;
00259   do {
00260     int result = blockUntilReadable(env, socket, timeout);
00261     if (timeout != NULL && result == 0) {
00262       bytesRead = 0;
00263       break;
00264     } else if (result <= 0) {
00265       break;
00266     }
00267     
00268     SOCKLEN_T addressSize = sizeof fromAddress;
00269     bytesRead = recvfrom(socket, (char*)buffer, bufferSize, 0,
00270                          (struct sockaddr*)&fromAddress,
00271                          &addressSize);
00272     if (bytesRead < 0) {
00273       //##### HACK to work around bugs in Linux and Windows:
00274       int err = env.getErrno();
00275       if (err == 111 /*ECONNREFUSED (Linux)*/
00276 #if defined(__WIN32__) || defined(_WIN32)
00277           // What a piece of crap Windows is.  Sometimes
00278           // recvfrom() returns -1, but with an 'errno' of 0.
00279           // This appears not to be a real error; just treat
00280           // it as if it were a read of zero bytes, and hope
00281           // we don't have to do anything else to 'reset'
00282           // this alleged error:
00283           || err == 0
00284 #else
00285           || err == EAGAIN
00286 #endif
00287           || err == 113 /*EHOSTUNREACH (Linux)*/) {
00288                                 //Why does Linux return this for datagram sock?
00289         fromAddress.sin_addr.s_addr = 0;
00290         return 0;
00291       }
00292       //##### END HACK
00293       socketErr(env, "recvfrom() error: ");
00294       break;
00295     }
00296   } while (0);
00297   
00298   return bytesRead;
00299 }

int readSocketExact ( UsageEnvironment env,
int  socket,
unsigned char *  buffer,
unsigned  bufferSize,
struct sockaddr_in &  fromAddress,
struct timeval *  timeout 
)

Definition at line 302 of file GroupsockHelper.cpp.

References env, and readSocket().

Referenced by RTSPClient::getResponse1(), and SocketDescriptor::tcpReadHandler().

00305                                              {
00306   /* read EXACTLY bufferSize bytes from the socket into the buffer.
00307      fromaddress is address of last read.
00308      return the number of bytes acually read when an error occurs
00309   */
00310   int bsize = bufferSize;
00311   int bytesRead = 0;
00312   int totBytesRead =0;
00313   do {
00314     bytesRead = readSocket (env, socket, buffer + totBytesRead, bsize,
00315                             fromAddress, timeout);
00316     if (bytesRead <= 0) break;
00317     totBytesRead += bytesRead;
00318     bsize -= bytesRead;
00319   } while (bsize != 0);
00320 
00321   return totBytesRead;
00322 }

static unsigned setBufferTo ( UsageEnvironment env,
int  bufOptName,
int  socket,
unsigned  requestedSize 
) [static]

Definition at line 379 of file GroupsockHelper.cpp.

References env, getBufferSize(), and SOCKLEN_T.

Referenced by setReceiveBufferTo(), and setSendBufferTo().

00380                                                                 {
00381   SOCKLEN_T sizeSize = sizeof requestedSize;
00382   setsockopt(socket, SOL_SOCKET, bufOptName, (char*)&requestedSize, sizeSize);
00383 
00384   // Get and return the actual, resulting buffer size:
00385   return getBufferSize(env, bufOptName, socket);
00386 }

unsigned setReceiveBufferTo ( UsageEnvironment env,
int  socket,
unsigned  requestedSize 
)

Definition at line 391 of file GroupsockHelper.cpp.

References env, and setBufferTo().

Referenced by main().

00392                                                                 {
00393         return setBufferTo(env, SO_RCVBUF, socket, requestedSize);
00394 }

unsigned setSendBufferTo ( UsageEnvironment env,
int  socket,
unsigned  requestedSize 
)

Definition at line 387 of file GroupsockHelper.cpp.

References env, and setBufferTo().

00388                                                              {
00389         return setBufferTo(env, SO_SNDBUF, socket, requestedSize);
00390 }

int setupDatagramSocket ( UsageEnvironment env,
Port  port,
Boolean   
)

Definition at line 52 of file GroupsockHelper.cpp.

References closeSocket, env, initializeWinsockIfNecessary, MAKE_SOCKADDR_IN, Port::num(), ReceivingInterfaceAddr, reuseFlag, SendingInterfaceAddr, and socketErr().

Referenced by Socket::changePort(), ourIPAddress(), and Socket::Socket().

00058   {
00059   if (!initializeWinsockIfNecessary()) {
00060     socketErr(env, "Failed to initialize 'winsock': ");
00061     return -1;
00062   }
00063   
00064   int newSocket = socket(AF_INET, SOCK_DGRAM, 0);
00065   if (newSocket < 0) {
00066     socketErr(env, "unable to create datagram socket: ");
00067     return newSocket;
00068   }
00069   
00070   if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,
00071                  (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00072     socketErr(env, "setsockopt(SO_REUSEADDR) error: ");
00073     closeSocket(newSocket);
00074     return -1;
00075   }
00076   
00077 #if defined(__WIN32__) || defined(_WIN32)
00078   // Windoze doesn't properly handle SO_REUSEPORT or IP_MULTICAST_LOOP
00079 #else
00080 #ifdef SO_REUSEPORT
00081   if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,
00082                  (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00083     socketErr(env, "setsockopt(SO_REUSEPORT) error: ");
00084     closeSocket(newSocket);
00085     return -1;
00086   }
00087 #endif
00088   
00089 #ifdef IP_MULTICAST_LOOP
00090   const u_int8_t loop = (u_int8_t)setLoopback;
00091   if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
00092                  (const char*)&loop, sizeof loop) < 0) {
00093     socketErr(env, "setsockopt(IP_MULTICAST_LOOP) error: ");
00094     closeSocket(newSocket);
00095     return -1;
00096   }
00097 #endif
00098 #endif
00099   
00100   // Note: Windoze requires binding, even if the port number is 0
00101   netAddressBits addr = INADDR_ANY;
00102 #if defined(__WIN32__) || defined(_WIN32)
00103 #else
00104   if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {
00105 #endif
00106     if (port.num() == 0) addr = ReceivingInterfaceAddr;
00107     MAKE_SOCKADDR_IN(name, addr, port.num());
00108     if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {
00109       char tmpBuffer[100];
00110       sprintf(tmpBuffer, "bind() error (port number: %d): ",
00111               ntohs(port.num()));
00112       socketErr(env, tmpBuffer);
00113       closeSocket(newSocket);
00114       return -1;
00115     }
00116 #if defined(__WIN32__) || defined(_WIN32)
00117 #else
00118   }
00119 #endif
00120   
00121   // Set the sending interface for multicasts, if it's not the default:
00122   if (SendingInterfaceAddr != INADDR_ANY) {
00123     struct in_addr addr;
00124     addr.s_addr = SendingInterfaceAddr;
00125     
00126     if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_IF,
00127                    (const char*)&addr, sizeof addr) < 0) {
00128       socketErr(env, "error setting outgoing multicast interface: ");
00129       closeSocket(newSocket);
00130       return -1;
00131     }
00132   }
00133   
00134   return newSocket;
00135 }

int setupStreamSocket ( UsageEnvironment env,
Port  port,
Boolean  makeNonBlocking 
)

Definition at line 150 of file GroupsockHelper.cpp.

References closeSocket, env, initializeWinsockIfNecessary, MAKE_SOCKADDR_IN, makeSocketNonBlocking(), Port::num(), ReceivingInterfaceAddr, reuseFlag, and socketErr().

Referenced by MP3HTTPSource::createNew(), RTSPClient::openConnectionFromURL(), RTSPClient::setupHTTPTunneling(), RTSPServer::setUpOurSocket(), RTSPOverHTTPServer::setUpOurSocket(), and HTTPSink::setUpOurSocket().

00151                                                           {
00152   if (!initializeWinsockIfNecessary()) {
00153     socketErr(env, "Failed to initialize 'winsock': ");
00154     return -1;
00155   }
00156   
00157   int newSocket = socket(AF_INET, SOCK_STREAM, 0);
00158   if (newSocket < 0) {
00159     socketErr(env, "unable to create stream socket: ");
00160     return newSocket;
00161   }
00162   
00163   if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,
00164                  (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00165     socketErr(env, "setsockopt(SO_REUSEADDR) error: ");
00166     closeSocket(newSocket);
00167     return -1;
00168   }
00169   
00170   // SO_REUSEPORT doesn't really make sense for TCP sockets, so we
00171   // normally don't set them.  However, if you really want to do this
00172   // #define REUSE_FOR_TCP
00173 #ifdef REUSE_FOR_TCP
00174 #if defined(__WIN32__) || defined(_WIN32)
00175   // Windoze doesn't properly handle SO_REUSEPORT
00176 #else
00177 #ifdef SO_REUSEPORT
00178   if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,
00179                  (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00180     socketErr(env, "setsockopt(SO_REUSEPORT) error: ");
00181     closeSocket(newSocket);
00182     return -1;
00183   }
00184 #endif
00185 #endif
00186 #endif
00187 
00188   // Note: Windoze requires binding, even if the port number is 0
00189 #if defined(__WIN32__) || defined(_WIN32)
00190 #else
00191   if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {
00192 #endif
00193     MAKE_SOCKADDR_IN(name, ReceivingInterfaceAddr, port.num());
00194     if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {
00195       char tmpBuffer[100];
00196       sprintf(tmpBuffer, "bind() error (port number: %d): ",
00197               ntohs(port.num()));
00198       socketErr(env, tmpBuffer);
00199       closeSocket(newSocket);
00200       return -1;
00201     }
00202 #if defined(__WIN32__) || defined(_WIN32)
00203 #else
00204   }
00205 #endif
00206 
00207   if (makeNonBlocking) {
00208     if (!makeSocketNonBlocking(newSocket)) {
00209       socketErr(env, "failed to make non-blocking: ");
00210       closeSocket(newSocket);
00211       return -1;
00212     }
00213   }
00214 
00215   return newSocket;
00216 }

static void socketErr ( UsageEnvironment env,
char *  errorMsg 
) [static]

Definition at line 38 of file GroupsockHelper.cpp.

References env, and UsageEnvironment::setResultErrMsg().

Referenced by blockUntilReadable(), getBufferSize(), getSourcePort(), readSocket(), setupDatagramSocket(), setupStreamSocket(), socketJoinGroup(), socketJoinGroupSSM(), and writeSocket().

00038                                                              {
00039         env.setResultErrMsg(errorMsg);
00040 }

Boolean socketJoinGroup ( UsageEnvironment env,
int  socket,
netAddressBits  groupAddress 
)

Definition at line 425 of file GroupsockHelper.cpp.

References env, False, UsageEnvironment::getErrno(), IsMulticastAddress(), ReceivingInterfaceAddr, socketErr(), and True.

Referenced by Groupsock::changeDestinationParameters(), Groupsock::Groupsock(), and ourIPAddress().

00426                                                     {
00427   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00428 
00429   struct ip_mreq imr;
00430   imr.imr_multiaddr.s_addr = groupAddress;
00431   imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00432   if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00433                  (const char*)&imr, sizeof (struct ip_mreq)) < 0) {
00434 #if defined(__WIN32__) || defined(_WIN32)
00435     if (env.getErrno() != 0) {
00436       // That piece-of-shit toy operating system (Windows) sometimes lies
00437       // about setsockopt() failing!
00438 #endif
00439       socketErr(env, "setsockopt(IP_ADD_MEMBERSHIP) error: ");
00440       return False;
00441 #if defined(__WIN32__) || defined(_WIN32)
00442     }
00443 #endif
00444   }
00445   
00446   return True;
00447 }

Boolean socketJoinGroupSSM ( UsageEnvironment env,
int  socket,
netAddressBits  groupAddress,
netAddressBits  sourceFilterAddr 
)

Definition at line 496 of file GroupsockHelper.cpp.

References env, False, ip_mreq_source::imr_interface, ip_mreq_source::imr_multiaddr, ip_mreq_source::imr_sourceaddr, IP_ADD_SOURCE_MEMBERSHIP, IsMulticastAddress(), ReceivingInterfaceAddr, socketErr(), and True.

Referenced by Groupsock::Groupsock().

00498                                                             {
00499   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00500 
00501   struct ip_mreq_source imr;
00502   imr.imr_multiaddr.s_addr = groupAddress;
00503   imr.imr_sourceaddr.s_addr = sourceFilterAddr;
00504   imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00505   if (setsockopt(socket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
00506                  (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) {
00507     socketErr(env, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP) error: ");
00508     return False;
00509   }
00510   
00511   return True;
00512 }

Boolean socketLeaveGroup ( UsageEnvironment ,
int  socket,
netAddressBits  groupAddress 
)

Definition at line 449 of file GroupsockHelper.cpp.

References False, IsMulticastAddress(), ReceivingInterfaceAddr, and True.

Referenced by Groupsock::changeDestinationParameters(), Groupsock::multicastSendOnly(), ourIPAddress(), and Groupsock::~Groupsock().

00450                                                       {
00451   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00452 
00453   struct ip_mreq imr;
00454   imr.imr_multiaddr.s_addr = groupAddress;
00455   imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00456   if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
00457                  (const char*)&imr, sizeof (struct ip_mreq)) < 0) {
00458     return