#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 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 |
| #define IP_DROP_SOURCE_MEMBERSHIP 26 |
| #define TTL_TYPE u_int8_t |
Referenced by writeSocket().
| 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