rtperror RTPSessionRemoveSendAddr(context cid, char *addr, u_int16 port, u_int8 ttl) { address_holder_t *holder; struct in_addr translation; hl_context *uc; rtperror err; err = RTPSessionGetHighLevelInfo(cid, (void**)&uc); if (err != RTP_OK) /* The cid is bogus */ return err; holder = uc->send_addr_list; /* If the port is odd, assume it's the RTCP port */ if((port & 1) == 1) port--; translation = host2ip(addr); if(translation.s_addr == (u_int32) -1) { return errordebug(RTP_BAD_ADDR, "RTPSessionRemoveSendAddr", "Could not resolve address"); } /* TTL matching is only done for multicast. For unicast, all TTL's are set to zero */ if(!IsMulticast(translation)) ttl = 0; while(holder != NULL) { if(!(holder->deleteflag) && (holder->address.s_addr == translation.s_addr) && (holder->port == htons(port)) && (holder->ttl == ttl)) break; holder = holder->next; } /* Now holder is either NULL if there was no match, else it points to the address which matched */ if(holder == NULL) { return errordebug(RTP_BAD_ADDR, "RTPSessionRemoveSendAddr", "No such address"); } else { holder->deleteflag = TRUE; return RTP_OK; } }
void KnxTelegram::InfoVerbose(String& str) const { byte payloadLength = GetPayloadLength(); str+= "Repeat="; str+= IsRepeated() ? "YES" : "NO"; str+="\nPrio="; switch(GetPriority()) { case KNX_PRIORITY_SYSTEM_VALUE : str+="SYSTEM"; break; case KNX_PRIORITY_ALARM_VALUE : str+="ALARM"; break; case KNX_PRIORITY_HIGH_VALUE : str+="HIGH"; break; case KNX_PRIORITY_NORMAL_VALUE : str+="NORMAL"; break; default : str+="ERR_VAL!"; break; } str+="\nSrcAddr=" + String(GetSourceAddress(),HEX); str+="\nTargetAddr=" + String(GetTargetAddress(),HEX); str+="\nGroupAddr="; if (IsMulticast()) str+= "YES"; else str+="NO"; str+="\nRout.Counter=" + String(GetRoutingCounter(),DEC); str+="\nPayloadLgth=" + String(payloadLength,DEC); str+="\nTelegramLength=" + String(GetTelegramLength(),DEC); str+="\nCommand="; switch(GetCommand()) { case KNX_COMMAND_VALUE_READ : str+="VAL_READ"; break; case KNX_COMMAND_VALUE_RESPONSE : str+="VAL_RESP"; break; case KNX_COMMAND_VALUE_WRITE : str+="VAL_WRITE"; break; case KNX_COMMAND_MEMORY_WRITE : str+="MEM_WRITE"; break; default : str+="ERR_VAL!"; break; } str+="\nPayload=" + String(GetFirstPayloadByte(),HEX)+' '; for (byte i = 0; i < payloadLength-1; i++) str+=String(_payloadChecksum[i], HEX)+' '; str+="\nValidity="; switch(GetValidity()) { case KNX_TELEGRAM_VALID : str+="VALID"; break; case KNX_TELEGRAM_INVALID_CONTROL_FIELD : str+="INVALID_CTRL_FIELD"; break; case KNX_TELEGRAM_UNSUPPORTED_FRAME_FORMAT : str+="UNSUPPORTED_FRAME_FORMAT"; break; case KNX_TELEGRAM_INCORRECT_PAYLOAD_LENGTH : str+="INCORRECT_PAYLOAD_LGTH"; break; case KNX_TELEGRAM_INVALID_COMMAND_FIELD : str+="INVALID_CMD_FIELD"; break; case KNX_TELEGRAM_UNKNOWN_COMMAND : str+="UNKNOWN_CMD"; break; case KNX_TELEGRAM_INCORRECT_CHECKSUM : str+="INCORRECT_CHKSUM"; break; default : str+="ERR_VAL!"; break; } str+='\n'; }
/* ------------------------------------------------------------------------- * Function : BmfTunPacketCaptured * Description: Handle an IP packet, captured outgoing on the tuntap interface * Input : encapsulationUdpData - space for the encapsulation header, followed by * the captured outgoing IP packet * Output : none * Return : none * Data Used : none * Notes : The packet is assumed to be captured on a socket of family * PF_PACKET and type SOCK_DGRAM (cooked). * ------------------------------------------------------------------------- */ static void BmfTunPacketCaptured(unsigned char* encapsulationUdpData) { union olsr_ip_addr srcIp; union olsr_ip_addr dstIp; union olsr_ip_addr broadAddr; struct TBmfInterface* walker; unsigned char* ipPacket; u_int16_t ipPacketLen; struct ip* ipHeader; u_int32_t crc32; struct TEncapHeader* encapHdr; #ifndef NODEBUG struct ipaddr_str srcIpBuf, dstIpBuf; #endif ipPacket = GetIpPacket(encapsulationUdpData); ipPacketLen = GetIpTotalLength(ipPacket); ipHeader = GetIpHeader(encapsulationUdpData); dstIp.v4 = ipHeader->ip_dst; broadAddr.v4.s_addr = htonl(EtherTunTapIpBroadcast); /* Only forward multicast packets. If configured, also forward local broadcast packets */ if (IsMulticast(&dstIp) || (EnableLocalBroadcast != 0 && ipequal(&dstIp, &broadAddr))) { /* continue */ } else { return; } srcIp.v4 = ipHeader->ip_src; OLSR_PRINTF( 8, "%s: outgoing pkt of %ld bytes captured on tuntap interface \"%s\": %s->%s\n", PLUGIN_NAME_SHORT, (long)ipPacketLen, EtherTunTapIfName, olsr_ip_to_string(&srcIpBuf, &srcIp), olsr_ip_to_string(&dstIpBuf, &dstIp)); /* Calculate packet fingerprint */ crc32 = PacketCrc32(ipPacket, ipPacketLen); /* Check if this packet was seen recently */ if (CheckAndMarkRecentPacket(crc32)) { OLSR_PRINTF( 8, "%s: --> discarding: packet is duplicate\n", PLUGIN_NAME_SHORT); return; } /* Compose encapsulation header */ encapHdr = (struct TEncapHeader*) encapsulationUdpData; memset (encapHdr, 0, ENCAP_HDR_LEN); encapHdr->type = BMF_ENCAP_TYPE; encapHdr->len = BMF_ENCAP_LEN; encapHdr->reserved = 0; encapHdr->crc32 = htonl(crc32); /* Check with each network interface what needs to be done on it */ for (walker = BmfInterfaces; walker != NULL; walker = walker->next) { /* Is the forwarding interface OLSR-enabled? */ if (walker->olsrIntf != NULL) { /* On an OLSR interface: encapsulate and forward packet. */ EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL); } else { /* On a non-OLSR interface: what to do? * Answer 1: nothing. Multicast routing between non-OLSR interfaces * is to be done by other protocols (e.g. PIM, DVMRP). * Answer 2 (better): Forward it. */ ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface"); } /* if */ } /* for */ } /* BmfTunPacketCaptured */
/* ------------------------------------------------------------------------- * Function : BmfPacketCaptured * Description: Handle a captured IP packet * Input : intf - the network interface on which the packet was captured * sllPkttype - the type of packet. Either PACKET_OUTGOING, * PACKET_BROADCAST or PACKET_MULTICAST. * encapsulationUdpData - space for the encapsulation header, followed by * the captured IP packet * Output : none * Return : none * Data Used : BmfInterfaces * Notes : The IP packet is assumed to be captured on a socket of family * PF_PACKET and type SOCK_DGRAM (cooked). * ------------------------------------------------------------------------- */ static void BmfPacketCaptured( struct TBmfInterface* intf, unsigned char sllPkttype, unsigned char* encapsulationUdpData) { union olsr_ip_addr src; /* Source IP address in captured packet */ union olsr_ip_addr dst; /* Destination IP address in captured packet */ union olsr_ip_addr* origIp; /* Main OLSR address of source of captured packet */ struct TBmfInterface* walker; int isFromOlsrIntf; int isFromOlsrNeighbor; int iAmMpr; unsigned char* ipPacket; /* The captured IP packet... */ u_int16_t ipPacketLen; /* ...and its length */ struct ip* ipHeader; /* The IP header inside the captured IP packet */ u_int32_t crc32; struct TEncapHeader* encapHdr; #ifndef NODEBUG struct ipaddr_str srcBuf, dstBuf; #endif ipHeader = GetIpHeader(encapsulationUdpData); dst.v4 = ipHeader->ip_dst; /* Only forward multicast packets. If configured, also forward local broadcast packets */ if (IsMulticast(&dst) || (EnableLocalBroadcast != 0 && ipequal(&dst, &intf->broadAddr))) { /* continue */ } else { return; } ipPacket = GetIpPacket(encapsulationUdpData); /* Don't forward fragments of IP packets: there is no way to distinguish fragments * of BMF encapsulation packets from other fragments. * Well yes, there is the IP-ID, which can be kept in a list to relate a fragment * to earlier sent BMF packets, but... sometimes the second fragment comes in earlier * than the first fragment, so that the list is not yet up to date and the second * fragment is not recognized as a BMF packet. * Also, don't forward OLSR packets (UDP port 698) and BMF encapsulated packets */ if (IsIpFragment(ipPacket) || IsOlsrOrBmfPacket(ipPacket)) { return; } /* Increase counter */ intf->nBmfPacketsRx++; /* Check if the frame is captured on an OLSR-enabled interface */ isFromOlsrIntf = (intf->olsrIntf != NULL); /* Retrieve the length of the captured packet */ ipPacketLen = GetIpTotalLength(ipPacket); src.v4 = ipHeader->ip_src; OLSR_PRINTF( 8, "%s: %s pkt of %ld bytes captured on %s interface \"%s\": %s->%s\n", PLUGIN_NAME_SHORT, sllPkttype == PACKET_OUTGOING ? "outgoing" : "incoming", (long)ipPacketLen, isFromOlsrIntf ? "OLSR" : "non-OLSR", intf->ifName, olsr_ip_to_string(&srcBuf, &src), olsr_ip_to_string(&dstBuf, &dst)); /* Lookup main address of source in the MID table of OLSR */ origIp = MainAddressOf(&src); /* Calculate packet fingerprint */ crc32 = PacketCrc32(ipPacket, ipPacketLen); /* Check if this packet was seen recently */ if (CheckAndMarkRecentPacket(crc32)) { /* Increase counter */ intf->nBmfPacketsRxDup++; OLSR_PRINTF( 8, "%s: --> discarding: packet is duplicate\n", PLUGIN_NAME_SHORT); return; } /* Compose encapsulation header */ encapHdr = (struct TEncapHeader*) encapsulationUdpData; memset (encapHdr, 0, ENCAP_HDR_LEN); encapHdr->type = BMF_ENCAP_TYPE; encapHdr->len = BMF_ENCAP_LEN; encapHdr->reserved = 0; encapHdr->crc32 = htonl(crc32); /* Check if the frame is captured on an OLSR interface from an OLSR neighbor. * TODO: get_best_link_to_neighbor() may be very CPU-expensive, a simpler call * would do here (something like 'get_any_link_to_neighbor()'). */ isFromOlsrNeighbor = (isFromOlsrIntf /* The frame is captured on an OLSR interface... */ && get_best_link_to_neighbor(origIp) != NULL); /* ...from an OLSR neighbor */ /* Check with OLSR if I am MPR for that neighbor */ iAmMpr = olsr_lookup_mprs_set(origIp) != NULL; /* Check with each network interface what needs to be done on it */ for (walker = BmfInterfaces; walker != NULL; walker = walker->next) { /* Is the forwarding interface OLSR-enabled? */ int isToOlsrIntf = (walker->olsrIntf != NULL); /* Depending on certain conditions, we decide whether or not to forward * the packet, and if it is forwarded, in which form (encapsulated * or not, TTL decreased or not). These conditions are: * - is the packet is coming in on an OLSR interface or not? (isFromOlsrIntf) * - is the packet going out on an OLSR interface or not? (isToOlsrIntf) * - if the packet if coming in on an OLSR interface: * - is the node that forwarded the packet my OLSR-neighbor? (isFromOlsrNeighbor) * - has the node that forwarded the packet selected me as MPR? (iAmMpr) * * Based on these conditions, the following cases can be distinguished: * * - Case 1: Packet coming in on an OLSR interface. What to * do with it on an OLSR interface? * Answer: * - Case 1.1: If the forwarding node is an OLSR neighbor that has *not* * selected me as MPR: don't forward the packet. * - Case 1.2: If the forwarding node is an OLSR neighbor that has selected * me as MPR: encapsulate and forward the packet. * - Case 1.3: If the forwarding node is not an OLSR neighbor: encapsulate * and forward the packet. * NOTE: Case 1.3 is a special case. In the perfect world, we expect to * see only OLSR-neighbors on OLSR-enabled interfaces. Sometimes, however, * ignorant users will connect a host not running OLSR, to a LAN in * which there are hosts running OLSR. Of course these ignorant users, * expecting magic, want to see their multicast packets being forwarded * through the network. * * - Case 2: Packet coming in on an OLSR interface. What to do with it on a * non-OLSR interface? * Answer: Forward it. * * - Case 3: Packet coming in on a non-OLSR interface. What to * do with it on an OLSR interface? * Answer: Encapsulate and forward it. * * - Case 4: Packet coming in on non-OLSR interface. What to do with it on a * non-OLSR interface? * Answer 1: nothing. Multicast routing between non-OLSR interfaces * is to be done by other protocols (e.g. PIM, DVMRP). * Answer 2 (better): Forward it. */ if (isFromOlsrIntf && isToOlsrIntf) { /* Case 1: Forward from an OLSR interface to an OLSR interface */ if (isFromOlsrNeighbor && !iAmMpr) { /* Case 1.1 */ { #ifndef NODEBUG struct ipaddr_str buf; #endif OLSR_PRINTF( 8, "%s: --> not encap-forwarding on \"%s\": I am not selected as MPR by neighbor %s\n", PLUGIN_NAME_SHORT, walker->ifName, olsr_ip_to_string(&buf, &src)); } } else if (sllPkttype == PACKET_OUTGOING && intf == walker) { OLSR_PRINTF( 8, "%s: --> not encap-forwarding on \"%s\": pkt was captured on that interface\n", PLUGIN_NAME_SHORT, walker->ifName); } else { /* Case 1.2 and 1.3 */ EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL); } } /* if (isFromOlsrIntf && isToOlsrIntf) */ else if (isFromOlsrIntf && !isToOlsrIntf) { /* Case 2: Forward from OLSR interface to non-OLSR interface */ ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded to non-OLSR interface"); } /* else if (isFromOlsrIntf && !isToOlsrIntf) */ else if (!isFromOlsrIntf && isToOlsrIntf) { /* Case 3: Forward from a non-OLSR interface to an OLSR interface. * Encapsulate and forward packet. */ EncapsulateAndForwardPacket(walker, encapsulationUdpData, NULL, NULL, NULL); } /* else if (!isFromOlsrIntf && isToOlsrIntf) */ else { /* Case 4: Forward from non-OLSR interface to non-OLSR interface. */ /* Don't forward on interface on which packet was received */ if (intf == walker) { OLSR_PRINTF( 8, "%s: --> not forwarding on \"%s\": pkt was captured on that interface\n", PLUGIN_NAME_SHORT, walker->ifName); } else { ForwardPacket (walker, ipPacket, ipPacketLen, "forwarded from non-OLSR to non-OLSR interface"); } /* if (intf == walker) */ } /* if */ } /* for */ } /* BmfPacketCaptured */
rtperror RTPOpenConnection(context cid){ struct sockaddr_in saddr; int dynamic_ports,bind_count,problem, nRet; socktype rtpskt, rtcpskt; hl_context *uc; rtperror err; err = RTPSessionGetHighLevelInfo(cid, (void**)&uc); if (err != RTP_OK) /* The cid is bogus */ return err; if (uc->connection_opened){ RTPCloseConnection(cid,NULL); } /* First check if the user has set the local address */ if(uc->recv_addr_list == NULL) { return errordebug(RTP_BAD_ADDR, "RTPOpenConnection", "Address not yet set"); } /* Set a flag for dynamic ports */ if(uc->recv_addr_list->port == 0) dynamic_ports = 1; else dynamic_ports = 0; /* For dynamic ports, we choose a port randomly, and try and bind to it, plus the one one higher for RTCP. If either fail, we iterate _BIND_COUNTER times, and then give up */ bind_count = 0; while(bind_count < _BIND_COUNTER) { bind_count++; /* We only use ports in the dynamic range - 49152 - 65535 */ if(dynamic_ports == 1) uc->recv_addr_list->port = htons(_UDP_PORT_BASE + 2 * ((u_int16) (drand48() * _UDP_PORT_RANGE))); /* Create the RTP and RTCP sockets */ uc->recv_addr_list->rtpsocket = _sys_create_socket(SOCK_DGRAM); rtpskt = uc->recv_addr_list->rtpsocket; if (uc->recv_addr_list->rtpsocket == _SYS_INVALID_SOCKET){ return errordebug(RTP_CANT_GET_SOCKET, "RTPOpenConnection", "couldn't get RTP socket for context %d", (int)cid); } uc->recv_addr_list->rtcpsocket = _sys_create_socket(SOCK_DGRAM); rtcpskt = uc->recv_addr_list->rtcpsocket; if (uc->recv_addr_list->rtcpsocket == _SYS_INVALID_SOCKET){ _sys_close_socket(rtpskt); return errordebug(RTP_CANT_GET_SOCKET, "RTPOpenConnection", "couldn't get RTCP socket for context %d", (int)cid); } if(_sys_set_reuseaddr(rtpskt) == _SYS_SOCKET_ERROR) { _sys_close_socket (rtpskt); _sys_close_socket (rtcpskt); return errordebug(RTP_CANT_SET_SOCKOPT, "RTPOpenConnection", "couldn't reuse RTP address for context %d", (int)cid); } if(_sys_set_reuseaddr(rtcpskt) == _SYS_SOCKET_ERROR) { _sys_close_socket(rtpskt); _sys_close_socket(rtcpskt); return errordebug(RTP_CANT_SET_SOCKOPT, "RTPOpenConnection", "couldn't reuse RTCP address for context %d", (int)cid); } if(_sys_set_reuseport(rtpskt) == _SYS_SOCKET_ERROR) { _sys_close_socket(rtpskt); _sys_close_socket(rtcpskt); return errordebug(RTP_CANT_SET_SOCKOPT, "RTPOpenConnection", "couldn't reuse RTP port for context %d", (int)cid); } if (_sys_set_reuseport(rtcpskt) == _SYS_SOCKET_ERROR) { _sys_close_socket(rtpskt); _sys_close_socket(rtcpskt); return errordebug(RTP_CANT_SET_SOCKOPT, "RTPOpenConnection", "couldn't reuse RTCP port for context %d", (int)cid); } /* bind sockets */ memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr = uc->recv_addr_list->address; saddr.sin_port = uc->recv_addr_list->port; /* If the address is multicast or null, bind to INADDR_ANY */ if((uc->recv_addr_list->address.s_addr == 0) || IsMulticast(saddr.sin_addr)) saddr.sin_addr.s_addr = INADDR_ANY; /* RTP port bind */ problem = 0; if((problem = _sys_bind(rtpskt, &saddr)) == _SYS_SOCKET_ADDRNOTAVAIL) { saddr.sin_addr.s_addr = INADDR_ANY; problem = _sys_bind(rtpskt, &saddr); } /* Address in use, try another port if we're doing dynamic ports */ if((problem == _SYS_SOCKET_ADDRINUSE) && (dynamic_ports == 1)) { _sys_close_socket(rtpskt); _sys_close_socket(rtcpskt); continue; } else if(problem != 0) { return errordebug(RTP_CANT_BIND_SOCKET, "RTPOpenConnection", "couldn't bind RTP address for context %d", (int)cid); } /* No error! */ saddr.sin_port = htons(ntohs(uc->recv_addr_list->port) + 1); /* Bind to RTCP port */ problem = 0; if((problem = _sys_bind(rtcpskt, &saddr)) == _SYS_SOCKET_ADDRNOTAVAIL) { /* The user specified a nonlocal address - probably they want to send to this as a unicast address, so try INADDR_ANY */ saddr.sin_addr.s_addr = INADDR_ANY; problem = _sys_bind(rtpskt, &saddr); } /* Address in use, try another port if we're doing dynamic ports */ if((problem == _SYS_SOCKET_ADDRINUSE) && (dynamic_ports == 1)) { _sys_close_socket(rtpskt); _sys_close_socket(rtcpskt); continue; } else if(problem != 0) { return errordebug(RTP_CANT_BIND_SOCKET, "RTPOpenConnection", "couldn't bind RTCP address for context %d", (int)cid); } break; } /* Now we are here either because of success, or looping too much */ if(bind_count == _BIND_COUNTER) { return errordebug(RTP_CANT_BIND_SOCKET, "RTPOpenConnection", "couldn't bind dynamic address for context %d", (int)cid); } /* Allow reuse of the address and port */ if (IsMulticast(uc->recv_addr_list->address)){ /* Multicast */ /* Every member of the session is a member of the multicast session */ memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr = uc->recv_addr_list->address; saddr.sin_port = uc->recv_addr_list->port; nRet = _sys_join_mcast_group(rtpskt, &saddr); if(nRet == _SYS_SOCKET_ERROR) { _sys_close_socket(rtpskt); _sys_close_socket(rtcpskt); return errordebug(RTP_CANT_SET_SOCKOPT, "RTPOpenConnection", "couldn't join RTP multicast group for context %d", (int)cid); } nRet = _sys_join_mcast_group(rtcpskt, &saddr); if(nRet == _SYS_SOCKET_ERROR) { _sys_close_socket(rtpskt); _sys_close_socket(rtcpskt); return errordebug(RTP_CANT_SET_SOCKOPT, "RTPOpenConnection", "couldn't join RTCP multicast group for context %d", (int)cid); } } /* Schedule the first rtcp packet, and initialize some data structures */ err = RTPStartSession(cid); if (err != RTP_OK) return err; uc->connection_opened = TRUE; return RTP_OK; }
rtperror RTPSessionAddSendAddr(context cid, char *addr, u_int16 port, u_int8 ttl){ address_holder_t *holder; struct sockaddr_in saddr; int len, nRet; struct in_addr translation; hl_context *uc; rtperror err; err = RTPSessionGetHighLevelInfo(cid, (void**)&uc); if (err != RTP_OK) /* The cid is bogus */ return err; if (port == 0) { return errordebug(RTP_BAD_PORT, "RTPSessionAddSendAddr", "Port number zero not allowed"); } /* If the port is odd, assume it's the RTCP port */ if((port & 1) == 1) port--; if((holder = (address_holder_t *) malloc(sizeof(address_holder_t))) == 0) { return errordebug(RTP_CANT_ALLOC_MEM, "RTPSessionAddSendAddr", "Cannot allocate memory"); } /* Translate address */ translation = host2ip(addr); if(translation.s_addr == (u_int32) -1) { free(holder); return errordebug(RTP_BAD_ADDR, "RTPSessionAddSendAddr", "Could not resolve address"); } /* Write values of address, port to context */ holder->address = translation; holder->port = htons(port); holder->deleteflag = FALSE; holder->ttl = 0; if(IsMulticast(translation)) holder->ttl = ttl; /* Create the RTP and RTCP sockets for this sender */ holder->rtpsocket = _sys_create_socket(SOCK_DGRAM); if (holder->rtpsocket == _SYS_INVALID_SOCKET){ free(holder); return errordebug(RTP_CANT_GET_SOCKET, "RTPSessionAddSendAddr", "couldn't get RTP socket for context %d", (int)cid); } holder->rtcpsocket = _sys_create_socket(SOCK_DGRAM); if (holder->rtcpsocket == _SYS_INVALID_SOCKET){ _sys_close_socket(holder->rtpsocket); free(holder); return errordebug(RTP_CANT_GET_SOCKET, "RTPSessionAddSendAddr", "couldn't get RTCP socket for context %d", (int)cid); } /* Connect them, first RTP socket */ memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr = holder->address; saddr.sin_port = htons(port); if(_sys_connect_socket(holder->rtpsocket, &saddr) == _SYS_SOCKET_ERROR) { err = errordebug(RTP_CANT_GET_SOCKET, "RTPSessionAddSendAddr", "couldn't connect RTP socket for context %d", (int)cid); goto bailout; } /* Now RTCP socket */ saddr.sin_port = htons(port+1); if(_sys_connect_socket(holder->rtcpsocket, &saddr) == _SYS_SOCKET_ERROR) { err = errordebug(RTP_CANT_GET_SOCKET, "RTPSessionAddSendAddr", "couldn't connect RTCP socket for context %d", (int)cid); goto bailout; } if(IsMulticast(holder->address)) { /* Set multicast TTL if needed */ nRet = _sys_set_ttl(holder->rtpsocket, ttl); if(nRet == _SYS_SOCKET_ERROR) { err = errordebug(RTP_CANT_SET_SOCKOPT, "RTPSessionAddSendAddr", "couldn't set RTP TTL for context %d", (int)cid); goto bailout; } nRet = _sys_set_ttl(holder->rtcpsocket, ttl); if(nRet == _SYS_SOCKET_ERROR) { err = errordebug(RTP_CANT_SET_SOCKOPT, "RTPSessionAddSendAddr", "couldn't set RTCP TTL for context %d", (int)cid); goto bailout; } /* Determine source addresses, for loopback detection */ /* XXX: multiple multicast destinations might have different sources */ len = sizeof(struct sockaddr_in); if(_sys_get_socket_name(holder->rtpsocket, &uc->rtp_sourceaddr) == _SYS_SOCKET_ERROR) { err = errordebug(RTP_CANT_GET_SOCKET, "RTPSessionAddSendAddr", "Couldn't get RTP source address for context %d", (int)cid); goto bailout; } if(_sys_get_socket_name(holder->rtcpsocket, &uc->rtcp_sourceaddr) == _SYS_SOCKET_ERROR) { err = errordebug(RTP_CANT_GET_SOCKET, "RTPSessionAddSendAddr", "Couldn't get RTCP source address for context %d", (int)cid); goto bailout; } } /* Add address to list */ holder->next = uc->send_addr_list; uc->send_addr_list = holder; return RTP_OK; bailout: _sys_close_socket(holder->rtpsocket); _sys_close_socket(holder->rtcpsocket); free(holder); return err; }