#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.
| #define initializeWinsockIfNecessary | ( | ) | 1 |
Definition at line 30 of file GroupsockHelper.cpp.
Referenced by BasicUsageEnvironment::BasicUsageEnvironment(), 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 badAddressForUs | ( | netAddressBits | addr | ) | [static] |
Definition at line 539 of file GroupsockHelper.cpp.
Referenced by ourIPAddress().
00539 { 00540 // Check for some possible erroneous addresses: 00541 netAddressBits nAddr = htonl(addr); 00542 return (nAddr == 0x7F000001 /* 127.0.0.1 */ 00543 || nAddr == 0 00544 || nAddr == (netAddressBits)(~0)); 00545 }
| netAddressBits chooseRandomIPv4SSMAddress | ( | UsageEnvironment & | env | ) |
Definition at line 660 of file GroupsockHelper.cpp.
References env, our_random(), and ourIPAddress().
Referenced by main().
00660 { 00661 // First, a hack to ensure that our random number generator is seeded: 00662 (void) ourIPAddress(env); 00663 00664 // Choose a random address in the range [232.0.1.0, 232.255.255.255) 00665 // i.e., [0xE8000100, 0xE8FFFFFF) 00666 netAddressBits const first = 0xE8000100, lastPlus1 = 0xE8FFFFFF; 00667 netAddressBits const range = lastPlus1 - first; 00668 00669 return ntohl(first + ((netAddressBits)our_random())%range); 00670 }
| 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 339 of file GroupsockHelper.cpp.
References env, socketErr(), and SOCKLEN_T.
Referenced by getReceiveBufferSize(), getSendBufferSize(), increaseBufferTo(), and setBufferTo().
00340 { 00341 unsigned curSize; 00342 SOCKLEN_T sizeSize = sizeof curSize; 00343 if (getsockopt(socket, SOL_SOCKET, bufOptName, 00344 (char*)&curSize, &sizeSize) < 0) { 00345 socketErr(env, "getBufferSize() error: "); 00346 return 0; 00347 } 00348 00349 return curSize; 00350 }
| unsigned getReceiveBufferSize | ( | UsageEnvironment & | env, | |
| int | socket | |||
| ) |
Definition at line 354 of file GroupsockHelper.cpp.
References env, and getBufferSize().
Referenced by continueAfterDESCRIBE().
00354 { 00355 return getBufferSize(env, SO_RCVBUF, socket); 00356 }
| unsigned getSendBufferSize | ( | UsageEnvironment & | env, | |
| int | socket | |||
| ) |
Definition at line 351 of file GroupsockHelper.cpp.
References env, and getBufferSize().
00351 { 00352 return getBufferSize(env, SO_SNDBUF, socket); 00353 }
| Boolean getSourcePort | ( | UsageEnvironment & | env, | |
| int | socket, | |||
| Port & | port | |||
| ) |
Definition at line 522 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().
00522 { 00523 portNumBits portNum = 0; 00524 if (!getSourcePort0(socket, portNum) || portNum == 0) { 00525 // Hack - call bind(), then try again: 00526 MAKE_SOCKADDR_IN(name, INADDR_ANY, 0); 00527 bind(socket, (struct sockaddr*)&name, sizeof name); 00528 00529 if (!getSourcePort0(socket, portNum) || portNum == 0) { 00530 socketErr(env, "getsockname() error: "); 00531 return False; 00532 } 00533 } 00534 00535 port = Port(portNum); 00536 return True; 00537 }
| static Boolean getSourcePort0 | ( | int | socket, | |
| portNumBits & | resultPortNum | |||
| ) | [static] |
Definition at line 513 of file GroupsockHelper.cpp.
References False, SOCKLEN_T, and True.
Referenced by getSourcePort().
00513 { 00514 sockaddr_in test; test.sin_port = 0; 00515 SOCKLEN_T len = sizeof test; 00516 if (getsockname(socket, (struct sockaddr*)&test, &len) < 0) return False; 00517 00518 resultPortNum = ntohs(test.sin_port); 00519 return True; 00520 }
| _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 375 of file GroupsockHelper.cpp.
References env, getBufferSize(), and SOCKLEN_T.
Referenced by increaseReceiveBufferTo(), and increaseSendBufferTo().
00376 { 00377 // First, get the current buffer size. If it's already at least 00378 // as big as what we're requesting, do nothing. 00379 unsigned curSize = getBufferSize(env, bufOptName, socket); 00380 00381 // Next, try to increase the buffer to the requested size, 00382 // or to some smaller size, if that's not possible: 00383 while (requestedSize > curSize) { 00384 SOCKLEN_T sizeSize = sizeof requestedSize; 00385 if (setsockopt(socket, SOL_SOCKET, bufOptName, 00386 (char*)&requestedSize, sizeSize) >= 0) { 00387 // success 00388 return requestedSize; 00389 } 00390 requestedSize = (requestedSize+curSize)/2; 00391 } 00392 00393 return getBufferSize(env, bufOptName, socket); 00394 }
| unsigned increaseReceiveBufferTo | ( | UsageEnvironment & | env, | |
| int | socket, | |||
| unsigned | requestedSize | |||
| ) |
Definition at line 399 of file GroupsockHelper.cpp.
References env, and increaseBufferTo().
Referenced by BasicUDPSource::BasicUDPSource(), MediaSubsession::initiate(), and MultiFramedRTPSource::MultiFramedRTPSource().
00400 { 00401 return increaseBufferTo(env, SO_RCVBUF, socket, requestedSize); 00402 }
| unsigned increaseSendBufferTo | ( | UsageEnvironment & | env, | |
| int | socket, | |||
| unsigned | requestedSize | |||
| ) |
Definition at line 395 of file GroupsockHelper.cpp.
References env, and increaseBufferTo().
Referenced by OnDemandServerMediaSubsession::getStreamParameters(), RTSPServer::incomingConnectionHandler(), RTPInterface::RTPInterface(), DarwinInjector::setDestination(), RTSPServer::setUpOurSocket(), and PassiveServerMediaSubsession::startStream().
00396 { 00397 return increaseBufferTo(env, SO_SNDBUF, socket, requestedSize); 00398 }
| 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 549 of file GroupsockHelper.cpp.
References badAddressForUs(), closeSocket, NetAddress::data(), env, iter, 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().
00549 { 00550 static netAddressBits ourAddress = 0; 00551 int sock = -1; 00552 struct in_addr testAddr; 00553 00554 if (ourAddress == 0) { 00555 // We need to find our source address 00556 struct sockaddr_in fromAddr; 00557 fromAddr.sin_addr.s_addr = 0; 00558 00559 // Get our address by sending a (0-TTL) multicast packet, 00560 // receiving it, and looking at the source address used. 00561 // (This is kinda bogus, but it provides the best guarantee 00562 // that other nodes will think our address is the same as we do.) 00563 do { 00564 loopbackWorks = 0; // until we learn otherwise 00565 00566 testAddr.s_addr = our_inet_addr("228.67.43.91"); // arbitrary 00567 Port testPort(15947); // ditto 00568 00569 sock = setupDatagramSocket(env, testPort); 00570 if (sock < 0) break; 00571 00572 if (!socketJoinGroup(env, sock, testAddr.s_addr)) break; 00573 00574 unsigned char testString[] = "hostIdTest"; 00575 unsigned testStringLength = sizeof testString; 00576 00577 if (!writeSocket(env, sock, testAddr, testPort, 0, 00578 testString, testStringLength)) break; 00579 00580 // Block until the socket is readable (with a 5-second timeout): 00581 fd_set rd_set; 00582 FD_ZERO(&rd_set); 00583 FD_SET((unsigned)sock, &rd_set); 00584 const unsigned numFds = sock+1; 00585 struct timeval timeout; 00586 timeout.tv_sec = 5; 00587 timeout.tv_usec = 0; 00588 int result = select(numFds, &rd_set, NULL, NULL, &timeout); 00589 if (result <= 0) break; 00590 00591 unsigned char readBuffer[20]; 00592 int bytesRead = readSocket(env, sock, 00593 readBuffer, sizeof readBuffer, 00594 fromAddr); 00595 if (bytesRead != (int)testStringLength 00596 || strncmp((char*)readBuffer, (char*)testString, testStringLength) != 0) { 00597 break; 00598 } 00599 00600 // We use this packet's source address, if it's good: 00601 loopbackWorks = !badAddressForUs(fromAddr.sin_addr.s_addr); 00602 } while (0); 00603 00604 if (sock >= 0) { 00605 socketLeaveGroup(env, sock, testAddr.s_addr); 00606 closeSocket(sock); 00607 } 00608 00609 if (!loopbackWorks) do { 00610 // We couldn't find our address using multicast loopback, 00611 // so try instead to look it up directly - by first getting our host name, and then resolving this host name 00612 char hostname[100]; 00613 hostname[0] = '\0'; 00614 int result = gethostname(hostname, sizeof hostname); 00615 if (result != 0 || hostname[0] == '\0') { 00616 env.setResultErrMsg("initial gethostname() failed"); 00617 break; 00618 } 00619 00620 // Try to resolve "hostname" to an IP address: 00621 NetAddressList addresses(hostname); 00622 NetAddressList::Iterator iter(addresses); 00623 NetAddress const* address; 00624 00625 // Take the first address that's not bad: 00626 netAddressBits addr = 0; 00627 while ((address = iter.nextAddress()) != NULL) { 00628 netAddressBits a = *(netAddressBits*)(address->data()); 00629 if (!badAddressForUs(a)) { 00630 addr = a; 00631 break; 00632 } 00633 } 00634 00635 // Assign the address that we found to "fromAddr" (as if the 'loopback' method had worked), to simplify the code below: 00636 fromAddr.sin_addr.s_addr = addr; 00637 } while (0); 00638 00639 // Make sure we have a good address: 00640 netAddressBits from = fromAddr.sin_addr.s_addr; 00641 if (badAddressForUs(from)) { 00642 char tmp[100]; 00643 sprintf(tmp, "This computer has an invalid IP address: %s", AddressString(from).val()); 00644 env.setResultMsg(tmp); 00645 from = 0; 00646 } 00647 00648 ourAddress = from; 00649 00650 // Use our newly-discovered IP address, and the current time, 00651 // to initialize the random number generator's seed: 00652 struct timeval timeNow; 00653 gettimeofday(&timeNow, NULL); 00654 unsigned seed = ourAddress^timeNow.tv_sec^timeNow.tv_usec; 00655 our_srandom(seed); 00656 } 00657 return ourAddress; 00658 }
| 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 358 of file GroupsockHelper.cpp.
References env, getBufferSize(), and SOCKLEN_T.
Referenced by setReceiveBufferTo(), and setSendBufferTo().
00359 { 00360 SOCKLEN_T sizeSize = sizeof requestedSize; 00361 setsockopt(socket, SOL_SOCKET, bufOptName, (char*)&requestedSize, sizeSize); 00362 00363 // Get and return the actual, resulting buffer size: 00364 return getBufferSize(env, bufOptName, socket); 00365 }
| unsigned setReceiveBufferTo | ( | UsageEnvironment & | env, | |
| int | socket, | |||
| unsigned | requestedSize | |||
| ) |
Definition at line 370 of file GroupsockHelper.cpp.
References env, and setBufferTo().
Referenced by continueAfterDESCRIBE().
00371 { 00372 return setBufferTo(env, SO_RCVBUF, socket, requestedSize); 00373 }
| unsigned setSendBufferTo | ( | UsageEnvironment & | env, | |
| int | socket, | |||
| unsigned | requestedSize | |||
| ) |
Definition at line 366 of file GroupsockHelper.cpp.
References env, and setBufferTo().
00367 { 00368 return setBufferTo(env, SO_SNDBUF, socket, requestedSize); 00369 }
| 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 404 of file GroupsockHelper.cpp.
References env, False, UsageEnvironment::getErrno(), IsMulticastAddress(), ReceivingInterfaceAddr, socketErr(), and True.
Referenced by Groupsock::changeDestinationParameters(), Groupsock::Groupsock(), and ourIPAddress().
00405 { 00406 if (!IsMulticastAddress(groupAddress)) return True; // ignore this case 00407 00408 struct ip_mreq imr; 00409 imr.imr_multiaddr.s_addr = groupAddress; 00410 imr.imr_interface.s_addr = ReceivingInterfaceAddr; 00411 if (setsockopt(socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, 00412 (const char*)&imr, sizeof (struct ip_mreq)) < 0) { 00413 #if defined(__WIN32__) || defined(_WIN32) 00414 if (env.getErrno() != 0) { 00415 // That piece-of-shit toy operating system (Windows) sometimes lies 00416 // about setsockopt() failing! 00417 #endif 00418 socketErr(env, "setsockopt(IP_ADD_MEMBERSHIP) error: "); 00419 return False; 00420 #if defined(__WIN32__) || defined(_WIN32) 00421 } 00422 #endif 00423 } 00424 00425 return True; 00426 }
| Boolean socketJoinGroupSSM | ( | UsageEnvironment & | env, | |
| int | socket, | |||
| netAddressBits | groupAddress, | |||
| netAddressBits | sourceFilterAddr | |||
| ) |
Definition at line 466 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().
00468 { 00469 if (!IsMulticastAddress(groupAddress)) return True; // ignore this case 00470 00471 struct ip_mreq_source imr; 00472 #ifdef ANDROID 00473 imr.imr_multiaddr = groupAddress; 00474 imr.imr_sourceaddr = sourceFilterAddr; 00475 imr.imr_interface = ReceivingInterfaceAddr; 00476 #else 00477 imr.imr_multiaddr.s_addr = groupAddress; 00478 imr.imr_sourceaddr.s_addr = sourceFilterAddr; 00479 imr.imr_interface.s_addr = ReceivingInterfaceAddr; 00480 #endif 00481 if (setsockopt(socket, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, 00482 (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) { 00483 socketErr(env, "setsockopt(IP_ADD_SOURCE_MEMBERSHIP) error: "); 00484 return False; 00485 } 00486 00487 return True; 00488 }
| Boolean socketLeaveGroup | ( | UsageEnvironment & | , | |
| int | socket, | |||
| netAddressBits | groupAddress | |||
| ) |
Definition at line 428 of file GroupsockHelper.cpp.
References False, IsMulticastAddress(), ReceivingInterfaceAddr, and True.
Referenced by Groupsock::changeDestinationParameters(), Groupsock::multicastSendOnly(), ourIPAddress(), and Groupsock::~Groupsock().
00429 { 00430 if (!IsMulticastAddress(groupAddress)) return True; // ignore this case 00431 00432 struct ip_mreq imr; 00433 imr.imr_multiaddr.s_addr = groupAddress; 00434 imr.imr_interface.s_addr = ReceivingInterfaceAddr; 00435 if (setsockopt(socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, 00436 (const char*)&imr, sizeof (struct ip_mreq)) < 0) { 00437 return False; 00438 } 00439 00440 return True; 00441 }
| Boolean socketLeaveGroupSSM | ( | UsageEnvironment & | , | |
| int | socket, | |||
| netAddressBits | groupAddress, | |||
| netAddressBits | sourceFilterAddr | |||
| ) |
Definition at line 490 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().
00492 { 00493 if (!IsMulticastAddress(groupAddress)) return True; // ignore this case 00494 00495 struct ip_mreq_source imr; 00496 #ifdef ANDROID 00497 imr.imr_multiaddr = groupAddress; 00498 imr.imr_sourceaddr = sourceFilterAddr; 00499 imr.imr_interface = ReceivingInterfaceAddr; 00500 #else 00501 imr.imr_multiaddr.s_addr = groupAddress; 00502 imr.imr_sourceaddr.s_addr = sourceFilterAddr; 00503 imr.imr_interface.s_addr = ReceivingInterfaceAddr; 00504 #endif 00505 if (setsockopt(socket, IPPROTO_IP, IP_DROP_SOURCE_MEMBERSHIP, 00506 (const char*)&imr, sizeof (struct ip_mreq_source)) < 0) { 00507 return False; 00508 } 00509 00510 return True; 00511 }
| char const* timestampString | ( | ) |
Definition at line 672 of file GroupsockHelper.cpp.
References NULL.
Referenced by operator<<().
00672 { 00673 struct timeval tvNow; 00674 gettimeofday(&tvNow, NULL); 00675 00676 #if !defined(_WIN32_WCE) 00677 static char timeString[9]; // holds hh:mm:ss plus trailing '\0' 00678 char const* ctimeResult = ctime((time_t*)&tvNow.tv_sec); 00679 if (ctimeResult == NULL) { 00680 sprintf(timeString, "??:??:??"); 00681 } else { 00682 char const* from = &ctimeResult[11]; 00683 int i; 00684 for (i = 0; i < 8; ++i) { 00685 timeString[i] = from[i]; 00686 } 00687 timeString[i] = '\0'; 00688 } 00689 #else 00690 // WinCE apparently doesn't have "ctime()", so instead, construct 00691 // a timestamp string just using the integer and fractional parts 00692 // of "tvNow": 00693 static char timeString[50]; 00694 sprintf(timeString, "%lu.%06ld", tvNow.tv_sec, tvNow.tv_usec); 00695 #endif 00696 00697 return (char const*)&timeString; 00698 }
| 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.
References env, False, MAKE_SOCKADDR_IN, Port::num(), socketErr(), True, and TTL_TYPE.
Referenced by ourIPAddress(), and OutputSocket::write().
00306 { 00307 do { 00308 if (ttlArg != 0) { 00309 // Before sending, set the socket's TTL: 00310 #if defined(__WIN32__) || defined(_WIN32) 00311 #define TTL_TYPE int 00312 #else 00313 #define TTL_TYPE u_int8_t 00314 #endif 00315 TTL_TYPE ttl = (TTL_TYPE)ttlArg; 00316 if (setsockopt(socket, IPPROTO_IP, IP_MULTICAST_TTL, 00317 (const char*)&ttl, sizeof ttl) < 0) { 00318 socketErr(env, "setsockopt(IP_MULTICAST_TTL) error: "); 00319 break; 00320 } 00321 } 00322 00323 MAKE_SOCKADDR_IN(dest, address.s_addr, port.num()); 00324 int bytesSent = sendto(socket, (char*)buffer, bufferSize, 0, 00325 (struct sockaddr*)&dest, sizeof dest); 00326 if (bytesSent != (int)bufferSize) { 00327 char tmpBuf[100]; 00328 sprintf(tmpBuf, "writeSocket(%d), sendTo() error: wrote %d bytes instead of %u: ", socket, bytesSent, bufferSize); 00329 socketErr(env, tmpBuf); 00330 break; 00331 } 00332 00333 return True; 00334 } while (0); 00335 00336 return False; 00337 }
| Boolean loopbackWorks = 1 |
| netAddressBits ReceivingInterfaceAddr = INADDR_ANY |
Definition at line 36 of file GroupsockHelper.cpp.
Referenced by RTSPServer::RTSPClientSession::handleCmd_SETUP(), main(), 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().
1.5.2