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)
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)
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 415 of file GroupsockHelper.cpp.

Referenced by socketJoinGroupSSM().

#define IP_DROP_SOURCE_MEMBERSHIP   26

Definition at line 416 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 482 of file GroupsockHelper.cpp.

Referenced by ourIPAddress().

00482                                                {
00483   // Check for some possible erroneous addresses:
00484   netAddressBits hAddr = ntohl(addr);
00485   return (hAddr == 0x7F000001 /* 127.0.0.1 */
00486           || hAddr == 0
00487           || hAddr == (netAddressBits)(~0));
00488 }

netAddressBits chooseRandomIPv4SSMAddress ( UsageEnvironment env  ) 

Definition at line 617 of file GroupsockHelper.cpp.

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

Referenced by main().

00617                                                                  {
00618   // First, a hack to ensure that our random number generator is seeded:
00619   (void) ourIPAddress(env);
00620 
00621   // Choose a random address in the range [232.0.1.0, 232.255.255.255)
00622   // i.e., [0xE8000100, 0xE8FFFFFF)
00623   netAddressBits const first = 0xE8000100, lastPlus1 = 0xE8FFFFFF;
00624   netAddressBits const range = lastPlus1 - first;
00625 
00626   return htonl(first + ((netAddressBits)our_random())%range);
00627 }

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

Definition at line 294 of file GroupsockHelper.cpp.

References env, socketErr(), and SOCKLEN_T.

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

00295                                           {
00296   unsigned curSize;
00297   SOCKLEN_T sizeSize = sizeof curSize;
00298   if (getsockopt(socket, SOL_SOCKET, bufOptName,
00299                  (char*)&curSize, &sizeSize) < 0) {
00300     socketErr(env, "getBufferSize() error: ");
00301     return 0;
00302   }
00303 
00304   return curSize;
00305 }

unsigned getReceiveBufferSize ( UsageEnvironment env,
int  socket 
)

Definition at line 309 of file GroupsockHelper.cpp.

References env, and getBufferSize().

Referenced by continueAfterDESCRIBE().

00309                                                                  {
00310   return getBufferSize(env, SO_RCVBUF, socket);
00311 }

unsigned getSendBufferSize ( UsageEnvironment env,
int  socket 
)

Definition at line 306 of file GroupsockHelper.cpp.

References env, and getBufferSize().

00306                                                               {
00307   return getBufferSize(env, SO_SNDBUF, socket);
00308 }

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

Definition at line 465 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().

00465                                                                      {
00466   portNumBits portNum = 0;
00467   if (!getSourcePort0(socket, portNum) || portNum == 0) {
00468     // Hack - call bind(), then try again:
00469     MAKE_SOCKADDR_IN(name, INADDR_ANY, 0);
00470     bind(socket, (struct sockaddr*)&name, sizeof name);
00471 
00472     if (!getSourcePort0(socket, portNum) || portNum == 0) {
00473       socketErr(env, "getsockname() error: ");
00474       return False;
00475     }
00476   }
00477 
00478   port = Port(portNum);
00479   return True;
00480 }

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

Definition at line 456 of file GroupsockHelper.cpp.

References False, SOCKLEN_T, and True.

Referenced by getSourcePort().

00456                                                                                     {
00457   sockaddr_in test; test.sin_port = 0;
00458   SOCKLEN_T len = sizeof test;
00459   if (getsockname(socket, (struct sockaddr*)&test, &len) < 0) return False;
00460 
00461   resultPortNum = ntohs(test.sin_port);
00462   return True;
00463 }

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

Definition at line 330 of file GroupsockHelper.cpp.

References env, getBufferSize(), and SOCKLEN_T.

Referenced by increaseReceiveBufferTo(), and increaseSendBufferTo().

00331                                                                      {
00332   // First, get the current buffer size.  If it's already at least
00333   // as big as what we're requesting, do nothing.
00334   unsigned curSize = getBufferSize(env, bufOptName, socket);
00335 
00336   // Next, try to increase the buffer to the requested size,
00337   // or to some smaller size, if that's not possible:
00338   while (requestedSize > curSize) {
00339     SOCKLEN_T sizeSize = sizeof requestedSize;
00340     if (setsockopt(socket, SOL_SOCKET, bufOptName,
00341                    (char*)&requestedSize, sizeSize) >= 0) {
00342       // success
00343       return requestedSize;
00344     }
00345     requestedSize = (requestedSize+curSize)/2;
00346   }
00347 
00348   return getBufferSize(env, bufOptName, socket);
00349 }

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

Definition at line 354 of file GroupsockHelper.cpp.

References env, and increaseBufferTo().

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

00355                                                                      {
00356   return increaseBufferTo(env, SO_RCVBUF, socket, requestedSize);
00357 }

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

Definition at line 350 of file GroupsockHelper.cpp.

References env, and increaseBufferTo().

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

00351                                                                   {
00352   return increaseBufferTo(env, SO_SNDBUF, socket, requestedSize);
00353 }

Boolean makeSocketBlocking ( int  sock  ) 

Definition at line 144 of file GroupsockHelper.cpp.

00144                                      {
00145 #if defined(__WIN32__) || defined(_WIN32) || defined(IMN_PIM)
00146   unsigned long arg = 0;
00147   return ioctlsocket(sock, FIONBIO, &arg) == 0;
00148 #elif defined(VXWORKS)
00149   int arg = 0;
00150   return ioctl(sock, FIONBIO, (int)&arg) == 0;
00151 #else
00152   int curFlags = fcntl(sock, F_GETFL, 0);
00153   return fcntl(sock, F_SETFL, curFlags&(~O_NONBLOCK)) >= 0;
00154 #endif
00155 }

Boolean makeSocketNonBlocking ( int  sock  ) 

Definition at line 131 of file GroupsockHelper.cpp.

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

00131                                         {
00132 #if defined(__WIN32__) || defined(_WIN32) || defined(IMN_PIM)
00133   unsigned long arg = 1;
00134   return ioctlsocket(sock, FIONBIO, &arg) == 0;
00135 #elif defined(VXWORKS)
00136   int arg = 1;
00137   return ioctl(sock, FIONBIO, (int)&arg) == 0;
00138 #else
00139   int curFlags = fcntl(sock, F_GETFL, 0);
00140   return fcntl(sock, F_SETFL, curFlags|O_NONBLOCK) >= 0;
00141 #endif
00142 }

netAddressBits ourIPAddress ( UsageEnvironment env  ) 

Definition at line 492 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().

00492                                                    {
00493   static netAddressBits ourAddress = 0;
00494   int sock = -1;
00495   struct in_addr testAddr;
00496 
00497   if (ourAddress == 0) {
00498     // We need to find our source address
00499     struct sockaddr_in fromAddr;
00500     fromAddr.sin_addr.s_addr = 0;
00501 
00502     // Get our address by sending a (0-TTL) multicast packet,
00503     // receiving it, and looking at the source address used.
00504     // (This is kinda bogus, but it provides the best guarantee
00505     // that other nodes will think our address is the same as we do.)
00506     do {
00507       loopbackWorks = 0; // until we learn otherwise
00508 
00509       testAddr.s_addr = our_inet_addr("228.67.43.91"); // arbitrary
00510       Port testPort(15947); // ditto
00511 
00512       sock = setupDatagramSocket(env, testPort);
00513       if (sock < 0) break;
00514 
00515       if (!socketJoinGroup(env, sock, testAddr.s_addr)) break;
00516 
00517       unsigned char testString[] = "hostIdTest";
00518       unsigned testStringLength = sizeof testString;
00519 
00520       if (!writeSocket(env, sock, testAddr, testPort, 0,
00521                        testString, testStringLength)) break;
00522 
00523       // Block until the socket is readable (with a 5-second timeout):
00524       fd_set rd_set;
00525       FD_ZERO(&rd_set);
00526       FD_SET((unsigned)sock, &rd_set);
00527       const unsigned numFds = sock+1;
00528       struct timeval timeout;
00529       timeout.tv_sec = 5;
00530       timeout.tv_usec = 0;
00531       int result = select(numFds, &rd_set, NULL, NULL, &timeout);
00532       if (result <= 0) break;
00533 
00534       unsigned char readBuffer[20];
00535       int bytesRead = readSocket(env, sock,
00536                                  readBuffer, sizeof readBuffer,
00537                                  fromAddr);
00538       if (bytesRead != (int)testStringLength
00539           || strncmp((char*)readBuffer, (char*)testString, testStringLength) != 0) {
00540         break;
00541       }
00542 
00543       loopbackWorks = 1;
00544     } while (0);
00545 
00546     if (!loopbackWorks) do {
00547       // We couldn't find our address using multicast loopback
00548       // so try instead to look it up directly.
00549       char hostname[100];
00550       hostname[0] = '\0';
00551       gethostname(hostname, sizeof hostname);
00552       if (hostname[0] == '\0') {
00553         env.setResultErrMsg("initial gethostname() failed");
00554         break;
00555       }
00556 
00557 #if defined(VXWORKS)
00558 #include <hostLib.h>
00559       if (ERROR == (ourAddress = hostGetByName( hostname ))) break;
00560 #else
00561       struct hostent* hstent
00562         = (struct hostent*)gethostbyname(hostname);
00563       if (hstent == NULL || hstent->h_length != 4) {
00564         env.setResultErrMsg("initial gethostbyname() failed");
00565         break;
00566       }
00567       // Take the first address that's not bad
00568       // (This code, like many others, won't handle IPv6)
00569       netAddressBits addr = 0;
00570       for (unsigned i = 0; ; ++i) {
00571         char* addrPtr = hstent->h_addr_list[i];
00572         if (addrPtr == NULL) break;
00573 
00574         netAddressBits a = *(netAddressBits*)addrPtr;
00575         if (!badAddress(a)) {
00576           addr = a;
00577           break;
00578         }
00579       }
00580       if (addr != 0) {
00581         fromAddr.sin_addr.s_addr = addr;
00582       } else {
00583         env.setResultMsg("no address");
00584         break;
00585       }
00586     } while (0);
00587 
00588     // Make sure we have a good address:
00589     netAddressBits from = fromAddr.sin_addr.s_addr;
00590     if (badAddress(from)) {
00591       char tmp[100];
00592       sprintf(tmp,
00593               "This computer has an invalid IP address: 0x%x",
00594               (netAddressBits)(ntohl(from)));
00595       env.setResultMsg(tmp);
00596       from = 0;
00597     }
00598 
00599     ourAddress = from;
00600 #endif
00601 
00602     if (sock >= 0) {
00603       socketLeaveGroup(env, sock, testAddr.s_addr);
00604       closeSocket(sock);
00605     }
00606 
00607     // Use our newly-discovered IP address, and the current time,
00608     // to initialize the random number generator's seed:
00609     struct timeval timeNow;
00610     gettimeofday(&timeNow, NULL);
00611     unsigned seed = ourAddress^timeNow.tv_sec^timeNow.tv_usec;
00612     our_srandom(seed);
00613   }
00614   return ourAddress;
00615 }

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

Definition at line 225 of file GroupsockHelper.cpp.

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

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

00227                                                 {
00228   SOCKLEN_T addressSize = sizeof fromAddress;
00229   int bytesRead = recvfrom(socket, (char*)buffer, bufferSize, 0,
00230                            (struct sockaddr*)&fromAddress,
00231                            &addressSize);
00232   if (bytesRead < 0) {
00233     //##### HACK to work around bugs in Linux and Windows:
00234     int err = env.getErrno();
00235     if (err == 111 /*ECONNREFUSED (Linux)*/
00236 #if defined(__WIN32__) || defined(_WIN32)
00237         // What a piece of crap Windows is.  Sometimes
00238         // recvfrom() returns -1, but with an 'errno' of 0.
00239         // This appears not to be a real error; just treat
00240         // it as if it were a read of zero bytes, and hope
00241         // we don't have to do anything else to 'reset'
00242         // this alleged error:
00243         || err == 0 || err == EWOULDBLOCK
00244 #else
00245         || err == EAGAIN
00246 #endif
00247         || err == 113 /*EHOSTUNREACH (Linux)*/) { // Why does Linux return this for datagram sock?
00248       fromAddress.sin_addr.s_addr = 0;
00249       return 0;
00250     }
00251     //##### END HACK
00252     socketErr(env, "recvfrom() error: ");
00253   }
00254 
00255   return bytesRead;
00256 }

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

Definition at line 313 of file GroupsockHelper.cpp.

References env, getBufferSize(), and SOCKLEN_T.

Referenced by setReceiveBufferTo(), and setSendBufferTo().

00314                                                                 {
00315   SOCKLEN_T sizeSize = sizeof requestedSize;
00316   setsockopt(socket, SOL_SOCKET, bufOptName, (char*)&requestedSize, sizeSize);
00317 
00318   // Get and return the actual, resulting buffer size:
00319   return getBufferSize(env, bufOptName, socket);
00320 }

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

Definition at line 325 of file GroupsockHelper.cpp.

References env, and setBufferTo().

Referenced by continueAfterDESCRIBE().

00326                                                                 {
00327         return setBufferTo(env, SO_RCVBUF, socket, requestedSize);
00328 }

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

Definition at line 321 of file GroupsockHelper.cpp.

References env, and setBufferTo().

00322                                                              {
00323         return setBufferTo(env, SO_SNDBUF, socket, requestedSize);
00324 }

int setupDatagramSocket ( UsageEnvironment env,
Port  port 
)

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().

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

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

Definition at line 157 of file GroupsockHelper.cpp.

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

Referenced by MP3HTTPSource::createNew(), RTSPClient::openConnection(), RTSPClient::responseHandlerForHTTP_GET1(), RTSPServer::setUpOurSocket(), RTSPOverHTTPServer::setUpOurSocket(), and HTTPSink::setUpOurSocket().

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

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 359 of file GroupsockHelper.cpp.

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

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

00360                                                     {
00361   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00362 
00363   struct ip_mreq imr;
00364   imr.imr_multiaddr.s_addr = groupAddress;
00365   imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00366   if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
00367                  (const char*)&imr, sizeof (struct ip_mreq)) < 0) {
00368 #if defined(__WIN32__) || defined(_WIN32)
00369     if (env.getErrno() != 0) {
00370       // That piece-of-shit toy operating system (Windows) sometimes lies
00371       // about setsockopt() failing!
00372 #endif
00373       socketErr(env, "setsockopt(IP_ADD_MEMBERSHIP) error: ");
00374       return False;
00375 #if defined(__WIN32__) || defined(_WIN32)
00376     }
00377 #endif
00378   }
00379 
00380   return True;
00381 }

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

Definition at line 421 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().

00423                                                             {
00424   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00425 
00426   struct ip_mreq_source imr;
00427   imr.imr_multiaddr.s_addr = groupAddress;
00428   imr.imr_sourceaddr.s_addr = sourceFilterAddr;
00429   imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00430   if (setsockopt(socket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP,
00431                  (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) {
00432     socketErr(env, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP) error: ");
00433     return False;
00434   }
00435 
00436   return True;
00437 }

Boolean socketLeaveGroup ( UsageEnvironment ,
int  socket,
netAddressBits  groupAddress 
)

Definition at line 383 of file GroupsockHelper.cpp.

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

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

00384                                                       {
00385   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00386 
00387   struct ip_mreq imr;
00388   imr.imr_multiaddr.s_addr = groupAddress;
00389   imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00390   if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
00391                  (const char*)&imr, sizeof (struct ip_mreq)) < 0) {
00392     return False;
00393   }
00394 
00395   return True;
00396 }

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

Definition at line 439 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().

00441                                                              {
00442   if (!IsMulticastAddress(groupAddress)) return True; // ignore this case
00443 
00444   struct ip_mreq_source imr;
00445   imr.imr_multiaddr.s_addr = groupAddress;
00446   imr.imr_sourceaddr.s_addr = sourceFilterAddr;
00447   imr.imr_interface.s_addr = ReceivingInterfaceAddr;
00448   if (setsockopt(socket, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP,
00449                  (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) {
00450     return False;
00451   }
00452 
00453   return True;
00454 }

char const* timestampString (  ) 

Definition at line 629 of file GroupsockHelper.cpp.

References NULL.

Referenced by operator<<().

00629                               {
00630   struct timeval tvNow;
00631   gettimeofday(&tvNow, NULL);
00632 
00633 #if !defined(_WIN32_WCE)
00634   static char timeString[9]; // holds hh:mm:ss plus trailing '\0'
00635   char const* ctimeResult = ctime((time_t*)&tvNow.tv_sec);
00636   char const* from = &ctimeResult[11];
00637   int i;
00638   for (i = 0; i < 8; ++i) {
00639     timeString[i] = from[i];
00640   }
00641   timeString[i] = '\0';
00642 #else
00643   // WinCE apparently doesn't have "ctime()", so instead, construct
00644   // a timestamp string just using the integer and fractional parts
00645   // of "tvNow":
00646   static char timeString[50];
00647   sprintf(timeString, "%lu.%06ld", tvNow.tv_sec, tvNow.tv_usec);
00648 #endif
00649 
00650   return (char const*)&timeString;
00651 }

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

Definition at line 258 of file GroupsockHelper.cpp.

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

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

00261                                                                 {
00262         do {
00263                 if (ttlArg != 0) {
00264                         // Before sending, set the socket's TTL:
00265 #if defined(__WIN32__) || defined(_WIN32)
00266 #define TTL_TYPE int
00267 #else
00268 #define TTL_TYPE u_int8_t
00269 #endif
00270                         TTL_TYPE ttl = (TTL_TYPE)ttlArg;
00271                         if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL,
00272                                        (const char*)&ttl, sizeof ttl) < 0) {
00273                                 socketErr(env, "setsockopt(IP_MULTICAST_TTL) error: ");
00274                                 break;
00275                         }
00276                 }
00277 
00278                 MAKE_SOCKADDR_IN(dest, address.s_addr, port.num());
00279                 int bytesSent = sendto(socket, (char*)buffer, bufferSize, 0,
00280                                        (struct sockaddr*)&dest, sizeof dest);
00281                 if (bytesSent != (int)bufferSize) {
00282                         char tmpBuf[100];
00283                         sprintf(tmpBuf, "writeSocket(%d), sendTo() error: wrote %d bytes instead of %u: ", socket, bytesSent, bufferSize);
00284                         socketErr(env, tmpBuf);
00285                         break;
00286                 }
00287 
00288                 return True;
00289         } while (0);
00290 
00291         return False;
00292 }


Variable Documentation

Boolean loopbackWorks = 1

Definition at line 490 of file GroupsockHelper.cpp.

Referenced by ourIPAddress().

netAddressBits ReceivingInterfaceAddr = INADDR_ANY

Definition at line 36 of file GroupsockHelper.cpp.

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

int reuseFlag = 1 [static]

Definition at line 42 of file GroupsockHelper.cpp.

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

netAddressBits SendingInterfaceAddr = INADDR_ANY

Definition at line 35 of file GroupsockHelper.cpp.

Referenced by setupDatagramSocket().


Generated on Fri Sep 3 02:35:44 2010 for live by  doxygen 1.5.2