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 const *errorMsg)
_groupsockPrivgroupsockPriv (UsageEnvironment &env)
void reclaimGroupsockPriv (UsageEnvironment &env)
static int createSocket (int type)
int setupDatagramSocket (UsageEnvironment &env, Port port)
Boolean makeSocketNonBlocking (int sock)
Boolean makeSocketBlocking (int sock)
int setupStreamSocket (UsageEnvironment &env, Port port, Boolean makeNonBlocking)
int readSocket (UsageEnvironment &env, int socket, unsigned char *buffer, unsigned bufferSize, struct sockaddr_in &fromAddress)
Boolean writeSocket (UsageEnvironment &env, int socket, struct in_addr address, Port port, u_int8_t ttlArg, unsigned char *buffer, unsigned bufferSize)
Boolean writeSocket (UsageEnvironment &env, int socket, struct in_addr address, Port port, 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)
static void clearMulticastAllSocketOption (int socket)
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 badAddressForUs (netAddressBits addr)
netAddressBits ourIPAddress (UsageEnvironment &env)
netAddressBits chooseRandomIPv4SSMAddress (UsageEnvironment &env)
char const * timestampString ()

Variables

netAddressBits SendingInterfaceAddr = INADDR_ANY
netAddressBits ReceivingInterfaceAddr = INADDR_ANY
Boolean loopbackWorks = 1


Define Documentation

 
#define initializeWinsockIfNecessary (  )     1

Definition at line 30 of file GroupsockHelper.cpp.

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

#define IP_ADD_SOURCE_MEMBERSHIP   25

Definition at line 477 of file GroupsockHelper.cpp.

Referenced by socketJoinGroupSSM().

#define IP_DROP_SOURCE_MEMBERSHIP   26

Definition at line 478 of file GroupsockHelper.cpp.

Referenced by socketLeaveGroupSSM().

#define TTL_TYPE   u_int8_t

Referenced by writeSocket().


Function Documentation

static Boolean badAddressForUs ( netAddressBits  addr  )  [static]

Definition at line 558 of file GroupsockHelper.cpp.

Referenced by ourIPAddress().

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

netAddressBits chooseRandomIPv4SSMAddress ( UsageEnvironment env  ) 

Definition at line 685 of file GroupsockHelper.cpp.

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

Referenced by main().

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

static void clearMulticastAllSocketOption ( int  socket  )  [static]

Definition at line 408 of file GroupsockHelper.cpp.

Referenced by socketJoinGroup(), and socketJoinGroupSSM().

00408                                                       {
00409 #ifdef IP_MULTICAST_ALL
00410   // This option is defined in modern versions of Linux to overcome a bug in the Linux kernel's default behavior.
00411   // When set to 0, it ensures that we receive only packets that were sent to the specified IP multicast address,
00412   // even if some other process on the same system has joined a different multicast group with the same port number.
00413   int multicastAll = 0;
00414   (void)setsockopt(socket, IPPROTO_IP, IP_MULTICAST_ALL, (void*)&multicastAll, sizeof multicastAll);
00415   // Ignore the call's result.  Should it fail, we'll still receive packets (just perhaps more than intended)
00416 #endif
00417 }

static int createSocket ( int  type  )  [static]

Definition at line 72 of file GroupsockHelper.cpp.

Referenced by setupDatagramSocket(), and setupStreamSocket().

00072                                   {
00073   // Call "socket()" to create a (IPv4) socket of the specified type.
00074   // But also set it to have the 'close on exec' property (if we can)
00075   int sock;
00076 
00077 #ifdef SOCK_CLOEXEC
00078   sock = socket(AF_INET, type|SOCK_CLOEXEC, 0);
00079   if (sock != -1 || errno != EINVAL) return sock;
00080   // An "errno" of EINVAL likely means that the system wasn't happy with the SOCK_CLOEXEC; fall through and try again without it:
00081 #endif
00082 
00083   sock = socket(AF_INET, type, 0);
00084 #ifdef FD_CLOEXEC
00085   if (sock != -1) fcntl(sock, F_SETFD, FD_CLOEXEC);
00086 #endif
00087   return sock;
00088 }

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

Definition at line 343 of file GroupsockHelper.cpp.

References env, socketErr(), and SOCKLEN_T.

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

00344                                           {
00345   unsigned curSize;
00346   SOCKLEN_T sizeSize = sizeof curSize;
00347   if (getsockopt(socket, SOL_SOCKET, bufOptName,
00348                  (char*)&curSize, &sizeSize) < 0) {
00349     socketErr(env, "getBufferSize() error: ");
00350     return 0;
00351   }
00352 
00353   return curSize;
00354 }

unsigned getReceiveBufferSize ( UsageEnvironment env,
int  socket 
)

Definition at line 358 of file GroupsockHelper.cpp.

References env, and getBufferSize().

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

00358                                                                  {
00359   return getBufferSize(env, SO_RCVBUF, socket);
00360 }

unsigned getSendBufferSize ( UsageEnvironment env,
int  socket 
)

Definition at line 355 of file GroupsockHelper.cpp.

References env, and getBufferSize().

Referenced by Socket::changePort().

00355                                                               {
00356   return getBufferSize(env, SO_SNDBUF, socket);
00357 }

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

Definition at line 541 of file GroupsockHelper.cpp.

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

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

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

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

Definition at line 532 of file GroupsockHelper.cpp.

References False, SOCKLEN_T, and True.

Referenced by getSourcePort().

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

_groupsockPriv* groupsockPriv ( UsageEnvironment env  ) 

Definition at line 53 of file GroupsockHelper.cpp.

References env, UsageEnvironment::groupsockPriv, NULL, _groupsockPriv::reuseFlag, and _groupsockPriv::socketTable.

Referenced by getSocketTable(), NoReuse::NoReuse(), setupDatagramSocket(), setupStreamSocket(), and NoReuse::~NoReuse().

00053                                                      {
00054   if (env.groupsockPriv == NULL) { // We need to create it
00055     _groupsockPriv* result = new _groupsockPriv;
00056     result->socketTable = NULL;
00057     result->reuseFlag = 1; // default value => allow reuse of socket numbers
00058     env.groupsockPriv = result;
00059   }
00060   return (_groupsockPriv*)(env.groupsockPriv);
00061 }

static unsigned increaseBufferTo ( 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 increaseReceiveBufferTo(), and increaseSendBufferTo().

00380                                                                      {
00381   // First, get the current buffer size.  If it's already at least
00382   // as big as what we're requesting, do nothing.
00383   unsigned curSize = getBufferSize(env, bufOptName, socket);
00384 
00385   // Next, try to increase the buffer to the requested size,
00386   // or to some smaller size, if that's not possible:
00387   while (requestedSize > curSize) {
00388     SOCKLEN_T sizeSize = sizeof requestedSize;
00389     if (setsockopt(socket, SOL_SOCKET, bufOptName,
00390                    (char*)&requestedSize, sizeSize) >= 0) {
00391       // success
00392       return requestedSize;
00393     }
00394     requestedSize = (requestedSize+curSize)/2;
00395   }
00396 
00397   return getBufferSize(env, bufOptName, socket);
00398 }

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

Definition at line 403 of file GroupsockHelper.cpp.

References env, and increaseBufferTo().

Referenced by BasicUDPSource::BasicUDPSource(), MediaSubsession::initiate(), and MultiFramedRTPSource::MultiFramedRTPSource().

00404                                                                      {
00405   return increaseBufferTo(env, SO_RCVBUF, socket, requestedSize);
00406 }

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

Definition at line 399 of file GroupsockHelper.cpp.

References env, and increaseBufferTo().

Referenced by OnDemandServerMediaSubsession::getStreamParameters(), RTSPServer::incomingConnectionHandler(), RTPInterface::RTPInterface(), DarwinInjector::setDestination(), RTSPServer::setUpOurSocket(), and PassiveServerMediaSubsession::startStream().

00400                                                                   {
00401   return increaseBufferTo(env, SO_SNDBUF, socket, requestedSize);
00402 }

Boolean makeSocketBlocking ( int  sock  ) 

Definition at line 184 of file GroupsockHelper.cpp.

Referenced by RTPInterface::sendDataOverTCP().

00184                                      {
00185 #if defined(__WIN32__) || defined(_WIN32)
00186   unsigned long arg = 0;
00187   return ioctlsocket(sock, FIONBIO, &arg) == 0;
00188 #elif defined(VXWORKS)
00189   int arg = 0;
00190   return ioctl(sock, FIONBIO, (int)&arg) == 0;
00191 #else
00192   int curFlags = fcntl(sock, F_GETFL, 0);
00193   return fcntl(sock, F_SETFL, curFlags&(~O_NONBLOCK)) >= 0;
00194 #endif
00195 }

Boolean makeSocketNonBlocking ( int  sock  ) 

Definition at line 171 of file GroupsockHelper.cpp.

Referenced by BasicUDPSource::BasicUDPSource(), ByteStreamFileSource::ByteStreamFileSource(), RTSPServer::incomingConnectionHandler(), RTPInterface::RTPInterface(), RTPInterface::sendDataOverTCP(), setupStreamSocket(), and WAVAudioFileSource::WAVAudioFileSource().

00171                                         {
00172 #if defined(__WIN32__) || defined(_WIN32)
00173   unsigned long arg = 1;
00174   return ioctlsocket(sock, FIONBIO, &arg) == 0;
00175 #elif defined(VXWORKS)
00176   int arg = 1;
00177   return ioctl(sock, FIONBIO, (int)&arg) == 0;
00178 #else
00179   int curFlags = fcntl(sock, F_GETFL, 0);
00180   return fcntl(sock, F_SETFL, curFlags|O_NONBLOCK) >= 0;
00181 #endif
00182 }

netAddressBits ourIPAddress ( UsageEnvironment env  ) 

Definition at line 568 of file GroupsockHelper.cpp.

References badAddressForUs(), closeSocket, NetAddress::data(), env, iter, loopbackWorks, NULL, our_inet_addr(), our_srandom(), readSocket(), ReceivingInterfaceAddr, 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().

00568                                                    {
00569   static netAddressBits ourAddress = 0;
00570   int sock = -1;
00571   struct in_addr testAddr;
00572 
00573   if (ReceivingInterfaceAddr != INADDR_ANY) {
00574     // Hack: If we were told to receive on a specific interface address, then 
00575     // define this to be our ip address:
00576     ourAddress = ReceivingInterfaceAddr;
00577   }
00578 
00579   if (ourAddress == 0) {
00580     // We need to find our source address
00581     struct sockaddr_in fromAddr;
00582     fromAddr.sin_addr.s_addr = 0;
00583 
00584     // Get our address by sending a (0-TTL) multicast packet,
00585     // receiving it, and looking at the source address used.
00586     // (This is kinda bogus, but it provides the best guarantee
00587     // that other nodes will think our address is the same as we do.)
00588     do {
00589       loopbackWorks = 0; // until we learn otherwise
00590 
00591       testAddr.s_addr = our_inet_addr("228.67.43.91"); // arbitrary
00592       Port testPort(15947); // ditto
00593 
00594       sock = setupDatagramSocket(env, testPort);
00595       if (sock < 0) break;
00596 
00597       if (!socketJoinGroup(env, sock, testAddr.s_addr)) break;
00598 
00599       unsigned char testString[] = "hostIdTest";
00600       unsigned testStringLength = sizeof testString;
00601 
00602       if (!writeSocket(env, sock, testAddr, testPort, 0,
00603                        testString, testStringLength)) break;
00604 
00605       // Block until the socket is readable (with a 5-second timeout):
00606       fd_set rd_set;
00607       FD_ZERO(&rd_set);
00608       FD_SET((unsigned)sock, &rd_set);
00609       const unsigned numFds = sock+1;
00610       struct timeval timeout;
00611       timeout.tv_sec = 5;
00612       timeout.tv_usec = 0;
00613       int result = select(numFds, &rd_set, NULL, NULL, &timeout);
00614       if (result <= 0) break;
00615 
00616       unsigned char readBuffer[20];
00617       int bytesRead = readSocket(env, sock,
00618                                  readBuffer, sizeof readBuffer,
00619                                  fromAddr);
00620       if (bytesRead != (int)testStringLength
00621           || strncmp((char*)readBuffer, (char*)testString, testStringLength) != 0) {
00622         break;
00623       }
00624 
00625       // We use this packet's source address, if it's good:
00626       loopbackWorks = !badAddressForUs(fromAddr.sin_addr.s_addr);
00627     } while (0);
00628 
00629     if (sock >= 0) {
00630       socketLeaveGroup(env, sock, testAddr.s_addr);
00631       closeSocket(sock);
00632     }
00633 
00634     if (!loopbackWorks) do {
00635       // We couldn't find our address using multicast loopback,
00636       // so try instead to look it up directly - by first getting our host name, and then resolving this host name
00637       char hostname[100];
00638       hostname[0] = '\0';
00639       int result = gethostname(hostname, sizeof hostname);
00640       if (result != 0 || hostname[0] == '\0') {
00641         env.setResultErrMsg("initial gethostname() failed");
00642         break;
00643       }
00644 
00645       // Try to resolve "hostname" to an IP address:
00646       NetAddressList addresses(hostname);
00647       NetAddressList::Iterator iter(addresses);
00648       NetAddress const* address;
00649 
00650       // Take the first address that's not bad:
00651       netAddressBits addr = 0;
00652       while ((address = iter.nextAddress()) != NULL) {
00653         netAddressBits a = *(netAddressBits*)(address->data());
00654         if (!badAddressForUs(a)) {
00655           addr = a;
00656           break;
00657         }
00658       }
00659 
00660       // Assign the address that we found to "fromAddr" (as if the 'loopback' method had worked), to simplify the code below: 
00661       fromAddr.sin_addr.s_addr = addr;
00662     } while (0);
00663 
00664     // Make sure we have a good address:
00665     netAddressBits from = fromAddr.sin_addr.s_addr;
00666     if (badAddressForUs(from)) {
00667       char tmp[100];
00668       sprintf(tmp, "This computer has an invalid IP address: %s", AddressString(from).val());
00669       env.setResultMsg(tmp);
00670       from = 0;
00671     }
00672 
00673     ourAddress = from;
00674 
00675     // Use our newly-discovered IP address, and the current time,
00676     // to initialize the random number generator's seed:
00677     struct timeval timeNow;
00678     gettimeofday(&timeNow, NULL);
00679     unsigned seed = ourAddress^timeNow.tv_sec^timeNow.tv_usec;
00680     our_srandom(seed);
00681   }
00682   return ourAddress;
00683 }

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

Definition at line 267 of file GroupsockHelper.cpp.

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

Referenced by RTPInterface::handleRead(), Groupsock::handleRead(), RTSPClient::incomingDataHandler1(), RTSPServer::RTSPClientConnection::incomingRequestHandler1(), ourIPAddress(), and SocketDescriptor::tcpReadHandler1().

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

void reclaimGroupsockPriv ( UsageEnvironment env  ) 

Definition at line 63 of file GroupsockHelper.cpp.

References env, UsageEnvironment::groupsockPriv, NULL, _groupsockPriv::reuseFlag, and _groupsockPriv::socketTable.

Referenced by setupDatagramSocket(), setupStreamSocket(), unsetGroupsockBySocket(), and NoReuse::~NoReuse().

00063                                                  {
00064   _groupsockPriv* priv = (_groupsockPriv*)(env.groupsockPriv);
00065   if (priv->socketTable == NULL && priv->reuseFlag == 1/*default value*/) {
00066     // We can delete the structure (to save space); it will get created again, if needed:
00067     delete priv;
00068     env.groupsockPriv = NULL;
00069   }
00070 }

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

Definition at line 362 of file GroupsockHelper.cpp.

References env, getBufferSize(), and SOCKLEN_T.

Referenced by setReceiveBufferTo(), and setSendBufferTo().

00363                                                                 {
00364   SOCKLEN_T sizeSize = sizeof requestedSize;
00365   setsockopt(socket, SOL_SOCKET, bufOptName, (char*)&requestedSize, sizeSize);
00366 
00367   // Get and return the actual, resulting buffer size:
00368   return getBufferSize(env, bufOptName, socket);
00369 }

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

Definition at line 374 of file GroupsockHelper.cpp.

References env, and setBufferTo().

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

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

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

Definition at line 370 of file GroupsockHelper.cpp.

References env, and setBufferTo().

Referenced by Socket::changePort().

00371                                                              {
00372         return setBufferTo(env, SO_SNDBUF, socket, requestedSize);
00373 }

int setupDatagramSocket ( UsageEnvironment env,
Port  port 
)

Definition at line 90 of file GroupsockHelper.cpp.

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

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

00090                                                           {
00091   if (!initializeWinsockIfNecessary()) {
00092     socketErr(env, "Failed to initialize 'winsock': ");
00093     return -1;
00094   }
00095 
00096   int newSocket = createSocket(SOCK_DGRAM);
00097   if (newSocket < 0) {
00098     socketErr(env, "unable to create datagram socket: ");
00099     return newSocket;
00100   }
00101 
00102   int reuseFlag = groupsockPriv(env)->reuseFlag;
00103   reclaimGroupsockPriv(env);
00104   if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,
00105                  (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00106     socketErr(env, "setsockopt(SO_REUSEADDR) error: ");
00107     closeSocket(newSocket);
00108     return -1;
00109   }
00110 
00111 #if defined(__WIN32__) || defined(_WIN32)
00112   // Windoze doesn't properly handle SO_REUSEPORT or IP_MULTICAST_LOOP
00113 #else
00114 #ifdef SO_REUSEPORT
00115   if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,
00116                  (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00117     socketErr(env, "setsockopt(SO_REUSEPORT) error: ");
00118     closeSocket(newSocket);
00119     return -1;
00120   }
00121 #endif
00122 
00123 #ifdef IP_MULTICAST_LOOP
00124   const u_int8_t loop = 1;
00125   if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
00126                  (const char*)&loop, sizeof loop) < 0) {
00127     socketErr(env, "setsockopt(IP_MULTICAST_LOOP) error: ");
00128     closeSocket(newSocket);
00129     return -1;
00130   }
00131 #endif
00132 #endif
00133 
00134   // Note: Windoze requires binding, even if the port number is 0
00135   netAddressBits addr = INADDR_ANY;
00136 #if defined(__WIN32__) || defined(_WIN32)
00137 #else
00138   if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {
00139 #endif
00140     if (port.num() == 0) addr = ReceivingInterfaceAddr;
00141     MAKE_SOCKADDR_IN(name, addr, port.num());
00142     if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {
00143       char tmpBuffer[100];
00144       sprintf(tmpBuffer, "bind() error (port number: %d): ",
00145               ntohs(port.num()));
00146       socketErr(env, tmpBuffer);
00147       closeSocket(newSocket);
00148       return -1;
00149     }
00150 #if defined(__WIN32__) || defined(_WIN32)
00151 #else
00152   }
00153 #endif
00154 
00155   // Set the sending interface for multicasts, if it's not the default:
00156   if (SendingInterfaceAddr != INADDR_ANY) {
00157     struct in_addr addr;
00158     addr.s_addr = SendingInterfaceAddr;
00159 
00160     if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_IF,
00161                    (const char*)&addr, sizeof addr) < 0) {
00162       socketErr(env, "error setting outgoing multicast interface: ");
00163       closeSocket(newSocket);
00164       return -1;
00165     }
00166   }
00167 
00168   return newSocket;
00169 }

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

Definition at line 197 of file GroupsockHelper.cpp.

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

Referenced by RTSPClient::openConnection(), RTSPClient::responseHandlerForHTTP_GET1(), and RTSPServer::setUpOurSocket().

00198                                                           {
00199   if (!initializeWinsockIfNecessary()) {
00200     socketErr(env, "Failed to initialize 'winsock': ");
00201     return -1;
00202   }
00203 
00204   int newSocket = createSocket(SOCK_STREAM);
00205   if (newSocket < 0) {
00206     socketErr(env, "unable to create stream socket: ");
00207     return newSocket;
00208   }
00209 
00210   int reuseFlag = groupsockPriv(env)->reuseFlag;
00211   reclaimGroupsockPriv(env);
00212   if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,
00213                  (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00214     socketErr(env, "setsockopt(SO_REUSEADDR) error: ");
00215     closeSocket(newSocket);
00216     return -1;
00217   }
00218 
00219   // SO_REUSEPORT doesn't really make sense for TCP sockets, so we
00220   // normally don't set them.  However, if you really want to do this
00221   // #define REUSE_FOR_TCP
00222 #ifdef REUSE_FOR_TCP
00223 #if defined(__WIN32__) || defined(_WIN32)
00224   // Windoze doesn't properly handle SO_REUSEPORT
00225 #else
00226 #ifdef SO_REUSEPORT
00227   if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,
00228                  (const char*)&reuseFlag, sizeof reuseFlag) < 0) {
00229     socketErr(env, "setsockopt(SO_REUSEPORT) error: ");
00230     closeSocket(newSocket);
00231     return -1;
00232   }
00233 #endif
00234 #endif
00235 #endif
00236 
00237   // Note: Windoze requires binding, even if the port number is 0
00238 #if defined(__WIN32__) || defined(_WIN32)
00239 #else
00240   if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {
00241 #endif
00242     MAKE_SOCKADDR_IN(name, ReceivingInterfaceAddr, port.num());
00243     if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {
00244       char tmpBuffer[100];
00245       sprintf(tmpBuffer, "bind() error (port number: %d): ",
00246               ntohs(port.num()));
00247       socketErr(env, tmpBuffer);
00248       closeSocket(newSocket);
00249       return -1;
00250     }
00251 #if defined(__WIN32__) || defined(_WIN32)
00252 #else
00253   }
00254 #endif
00255 
00256   if (makeNonBlocking) {
00257     if (!makeSocketNonBlocking(newSocket)) {
00258       socketErr(env, "failed to make non-blocking: ");
00259       closeSocket(newSocket);
00260       return -1;
00261     }
00262   }
00263 
00264   return newSocket;
00265 }

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

Definition at line 38 of file GroupsockHelper.cpp.

References env, and UsageEnvironment::setResultErrMsg().

Referenced by 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 419 of file GroupsockHelper.cpp.

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

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

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

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

Definition at line 483 of file GroupsockHelper.cpp.

References clearMulticastAllSocketOption(), 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().

00485                                                             {
00486   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00487 
00488   struct ip_mreq_source imr;
00489 #ifdef __ANDROID__
00490     imr.imr_multiaddr = groupAddress;
00491     imr.imr_sourceaddr = sourceFilterAddr;
00492     imr.imr_interface = ReceivingInterfaceAddr;
00493 #else
00494     imr.imr_multiaddr.s_addr = groupAddress;
00495     imr.imr_sourceaddr.s_addr = sourceFilterAddr;
00496     imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00497 #endif
00498   if (setsockopt(socket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
00499                  (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) {
00500     socketErr(env, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP) error: ");
00501     return False;
00502   }
00503 
00504   clearMulticastAllSocketOption(socket);
00505 
00506   return True;
00507 }

Boolean socketLeaveGroup ( UsageEnvironment ,
int  socket,
netAddressBits  groupAddress 
)

Definition at line 445 of file GroupsockHelper.cpp.

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

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

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

Boolean socketLeaveGroupSSM ( UsageEnvironment ,
int  socket,
netAddressBits  groupAddress,
netAddressBits  sourceFilterAddr 
)

Definition at line 509 of file GroupsockHelper.cpp.

References False, ip_mreq_source::imr_interface, ip_mreq_source::imr_multiaddr, ip_mreq_source::imr_sourceaddr, IP_DROP_SOURCE_MEMBERSHIP, IsMulticastAddress(), ReceivingInterfaceAddr, and True.

Referenced by Groupsock::~Groupsock().

00511                                                              {
00512   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00513 
00514   struct ip_mreq_source imr;
00515 #ifdef __ANDROID__
00516     imr.imr_multiaddr = groupAddress;
00517     imr.imr_sourceaddr = sourceFilterAddr;
00518     imr.imr_interface = ReceivingInterfaceAddr;
00519 #else
00520     imr.imr_multiaddr.s_addr = groupAddress;
00521     imr.imr_sourceaddr.s_addr = sourceFilterAddr;
00522     imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00523 #endif
00524   if (setsockopt(socket, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP,
00525                  (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) {
00526     return False;
00527   }
00528 
00529   return True;
00530 }

char const* timestampString (  ) 

Definition at line 697 of file GroupsockHelper.cpp.

References NULL.

Referenced by operator<<().

00697                               {
00698   struct timeval tvNow;
00699   gettimeofday(&tvNow, NULL);
00700 
00701 #if !defined(_WIN32_WCE)
00702   static char timeString[9]; // holds hh:mm:ss plus trailing '\0'
00703   char const* ctimeResult = ctime((time_t*)&tvNow.tv_sec);
00704   if (ctimeResult == NULL) {
00705     sprintf(timeString, "??:??:??");
00706   } else {
00707     char const* from = &ctimeResult[11];
00708     int i;
00709     for (i = 0; i < 8; ++i) {
00710       timeString[i] = from[i];
00711     }
00712     timeString[i] = '\0';
00713   }
00714 #else
00715   // WinCE apparently doesn't have "ctime()", so instead, construct
00716   // a timestamp string just using the integer and fractional parts
00717   // of "tvNow":
00718   static char timeString[50];
00719   sprintf(timeString, "%lu.%06ld", tvNow.tv_sec, tvNow.tv_usec);
00720 #endif
00721 
00722   return (char const*)&timeString;
00723 }

Boolean writeSocket ( UsageEnvironment env,
int  socket,
struct in_addr  address,
Port  port,
unsigned char *  buffer,
unsigned  bufferSize 
)

Definition at line 323 of file GroupsockHelper.cpp.

References env, False, MAKE_SOCKADDR_IN, Port::num(), socketErr(), and True.

00325                                                                 {
00326   do {
00327     MAKE_SOCKADDR_IN(dest, address.s_addr, port.num());
00328     int bytesSent = sendto(socket, (char*)buffer, bufferSize, 0,
00329                            (struct sockaddr*)&dest, sizeof dest);
00330     if (bytesSent != (int)bufferSize) {
00331       char tmpBuf[100];
00332       sprintf(tmpBuf, "writeSocket(%d), sendTo() error: wrote %d bytes instead of %u: ", socket, bytesSent, bufferSize);
00333       socketErr(env, tmpBuf);
00334       break;
00335     }
00336     
00337     return True;
00338   } while (0);
00339 
00340   return False;
00341 }

Boolean writeSocket ( UsageEnvironment env,
int  socket,
struct in_addr  address,
Port  port,
u_int8_t  ttlArg,
unsigned char *  buffer,
unsigned  bufferSize 
)

Definition at line 303 of file GroupsockHelper.cpp.

Referenced by ourIPAddress(), OutputSocket::write(), and writeSocket().

00306                                                                 {
00307   // Before sending, set the socket's TTL:
00308 #if defined(__WIN32__) || defined(_WIN32)
00309 #define TTL_TYPE int
00310 #else
00311 #define TTL_TYPE u_int8_t
00312 #endif
00313   TTL_TYPE ttl = (TTL_TYPE)ttlArg;
00314   if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL,
00315                  (const char*)&ttl, sizeof ttl) < 0) {
00316     socketErr(env, "setsockopt(IP_MULTICAST_TTL) error: ");
00317     return False;
00318   }
00319 
00320   return writeSocket(env, socket, address, port, buffer, bufferSize);
00321 }


Variable Documentation

Boolean loopbackWorks = 1

Definition at line 566 of file GroupsockHelper.cpp.

Referenced by ourIPAddress().

netAddressBits ReceivingInterfaceAddr = INADDR_ANY

Definition at line 36 of file GroupsockHelper.cpp.

Referenced by RTSPServer::RTSPClientSession::handleCmd_SETUP(), main(), ourIPAddress(), RTSPServer::rtspURLPrefix(), setupDatagramSocket(), setupStreamSocket(), socketJoinGroup(), socketJoinGroupSSM(), socketLeaveGroup(), and socketLeaveGroupSSM().

netAddressBits SendingInterfaceAddr = INADDR_ANY

Definition at line 35 of file GroupsockHelper.cpp.

Referenced by RTSPServer::RTSPClientSession::handleCmd_SETUP(), and setupDatagramSocket().


Generated on Tue Mar 25 14:35:42 2014 for live by  doxygen 1.5.2