live555 groupsock
groupsock的繼承關係
在OnDemandServerMediaSubsession 類中創建一個Groupsock,Groupsock的繼承關係如上圖所示。Groupsock()構造函數中的做了三件事情
- socket()構造函數建立UDP socket
- 創建destRecord結構記錄
- 創建GroupEId
Groupsock* OnDemandServerMediaSubsession
::createGroupsock(struct in_addr const& addr, Port port) {
// Default implementation; may be redefined by subclasses:
return new Groupsock(envir(), addr, port, 255);
}
Groupsock::Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr,
Port port, u_int8_t ttl)
: OutputSocket(env, port),
deleteIfNoMembers(False), isSlave(False),
fDests(new destRecord(groupAddr, port, ttl, 0, NULL)),
fIncomingGroupEId(groupAddr, port.num(), ttl) {
//如果地址是組播地址則加入多播組
if (!socketJoinGroup(env, socketNum(), groupAddr.s_addr)) {
if (DebugLevel >= 1) {
env << *this << ": failed to join group: "
<< env.getResultMsg() << "\n";
}
}
// Make sure we can get our source address: 測試是否可以獲得IP地址
if (ourIPAddress(env) == 0) {
if (DebugLevel >= 0) { // this is a fatal error
env << "Unable to determine our source address: "
<< env.getResultMsg() << "\n";
}
}
if (DebugLevel >= 2) env << *this << ": created\n";
}
OutputSocket()構造函數如下
OutputSocket::OutputSocket(UsageEnvironment& env, Port port)
: Socket(env, port),
fSourcePort(0), fLastSentTTL(256/*hack: a deliberately invalid value*/) {
}
Socket::Socket(UsageEnvironment& env, Port port)
: fEnv(DefaultUsageEnvironment != NULL ? *DefaultUsageEnvironment : env), fPort(port) {
fSocketNum = setupDatagramSocket(fEnv, port);
}
int setupDatagramSocket(UsageEnvironment& env, Port port) {
if (!initializeWinsockIfNecessary()) {
socketErr(env, "Failed to initialize 'winsock': ");
return -1;
}
int newSocket = createSocket(SOCK_DGRAM);
if (newSocket < 0) {
socketErr(env, "unable to create datagram socket: ");
return newSocket;
}
int reuseFlag = groupsockPriv(env)->reuseFlag;
reclaimGroupsockPriv(env);
if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR,
(const char*)&reuseFlag, sizeof reuseFlag) < 0) {
socketErr(env, "setsockopt(SO_REUSEADDR) error: ");
closeSocket(newSocket);
return -1;
}
#if defined(__WIN32__) || defined(_WIN32)
// Windoze doesn't properly handle SO_REUSEPORT or IP_MULTICAST_LOOP
#else
#ifdef SO_REUSEPORT
if (setsockopt(newSocket, SOL_SOCKET, SO_REUSEPORT,
(const char*)&reuseFlag, sizeof reuseFlag) < 0) {
socketErr(env, "setsockopt(SO_REUSEPORT) error: ");
closeSocket(newSocket);
return -1;
}
#endif
#ifdef IP_MULTICAST_LOOP
const u_int8_t loop = 1;
if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_LOOP,
(const char*)&loop, sizeof loop) < 0) {
socketErr(env, "setsockopt(IP_MULTICAST_LOOP) error: ");
closeSocket(newSocket);
return -1;
}
#endif
#endif
// Note: Windoze requires binding, even if the port number is 0
netAddressBits addr = INADDR_ANY;
#if defined(__WIN32__) || defined(_WIN32)
#else
if (port.num() != 0 || ReceivingInterfaceAddr != INADDR_ANY) {
#endif
if (port.num() == 0) addr = ReceivingInterfaceAddr;
MAKE_SOCKADDR_IN(name, addr, port.num());
if (bind(newSocket, (struct sockaddr*)&name, sizeof name) != 0) {
char tmpBuffer[100];
sprintf(tmpBuffer, "bind() error (port number: %d): ",
ntohs(port.num()));
socketErr(env, tmpBuffer);
closeSocket(newSocket);
return -1;
}
#if defined(__WIN32__) || defined(_WIN32)
#else
}
#endif
// Set the sending interface for multicasts, if it's not the default:
if (SendingInterfaceAddr != INADDR_ANY) {
struct in_addr addr;
addr.s_addr = SendingInterfaceAddr;
if (setsockopt(newSocket, IPPROTO_IP, IP_MULTICAST_IF,
(const char*)&addr, sizeof addr) < 0) {
socketErr(env, "error setting outgoing multicast interface: ");
closeSocket(newSocket);
return -1;
}
}
return newSocket;
}