bool RTPTransport::localAddr(SocketAddr& addr, bool rtcp) { // check if sockets are already created and bound if (m_rtpSock.valid()) return false; int p = addr.port(); // for RTCP make sure we don't have a port or it's an even one if (rtcp && (p & 1)) return false; m_warnSendErrorRtp = true; m_warnSendErrorRtcp = true; if (m_rtpSock.create(addr.family(),SOCK_DGRAM) && m_rtpSock.bind(addr)) { m_rtpSock.setBlocking(false); if (!rtcp) { // RTCP not requested - we are done m_rtpSock.getSockName(addr); m_localAddr = addr; setScopeId(m_localAddr,m_remoteAddr,m_remotePref); return true; } if (!p) { m_rtpSock.getSockName(addr); p = addr.port(); if (p & 1) { // allocated odd port - have to swap sockets m_rtcpSock.attach(m_rtpSock.detach()); addr.port(p-1); if (m_rtpSock.create(addr.family(),SOCK_DGRAM) && m_rtpSock.bind(addr)) { m_rtpSock.setBlocking(false); m_localAddr = addr; setScopeId(m_localAddr,m_remoteAddr,m_remoteRTCP,&m_remotePref); return true; } DDebug(DebugMild,"RTP Socket failed with code %d",m_rtpSock.error()); m_rtpSock.terminate(); m_rtcpSock.terminate(); return false; } } addr.port(p+1); if (m_rtcpSock.create(addr.family(),SOCK_DGRAM) && m_rtcpSock.bind(addr)) { m_rtcpSock.setBlocking(false); addr.port(p); m_localAddr = addr; setScopeId(m_localAddr,m_remoteAddr,m_remoteRTCP,&m_remotePref); return true; } #ifdef DEBUG else Debug(DebugMild,"RTCP Socket failed with code %d",m_rtcpSock.error()); #endif } #ifdef DEBUG else Debug(DebugMild,"RTP Socket failed with code %d",m_rtpSock.error()); #endif m_rtpSock.terminate(); m_rtcpSock.terminate(); return false; }
// Set IPv6 sin6_scope_id for remote addresses from local address // recvFrom() will set the sin6_scope_id of the remote socket address // This will avoid socket address comparison mismatch (same address, different scope id) static inline void setScopeId(const SocketAddr& local, SocketAddr& sa1, SocketAddr& sa2, SocketAddr* sa3 = 0) { if (local.family() != SocketAddr::IPv6) return; unsigned int val = local.scopeId(); sa1.scopeId(val); sa2.scopeId(val); if (sa3) sa3->scopeId(val); }