1 /* 2 * Copyright (C) 2002-2003 Fhg Fokus 3 * 4 * This file is part of SEMS, a free SIP media server. 5 * 6 * SEMS is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. This program is released under 10 * the GPL with the additional exemption that compiling, linking, 11 * and/or using OpenSSL is allowed. 12 * 13 * For a license to use the SEMS software under conditions 14 * other than those described here, or to purchase support for this 15 * software, please contact iptel.org by e-mail at the following addresses: 16 * info@iptel.org 17 * 18 * SEMS is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 */ 27 28 #define __APPLE_USE_RFC_3542 29 #include <netinet/in.h> 30 31 #include "AmRtpPacket.h" 32 #include "rtp/rtp.h" 33 #include "log.h" 34 #include "AmConfig.h" 35 36 #include "sip/raw_sender.h" 37 #include "sip/ip_util.h" 38 39 #include <assert.h> 40 #include <string.h> 41 #include <errno.h> 42 43 #include <sys/socket.h> 44 #include <arpa/inet.h> 45 46 #include "sip/msg_logger.h" 47 48 #include "AmRtpMuxStream.h" 49 50 AmRtpPacket::AmRtpPacket() 51 : data_offset(0) 52 { 53 // buffer will be overwritten by received packet 54 // of hdr+data - does not need to be set to 0s 55 // memset(buffer,0,4096); 56 } 57 58 AmRtpPacket::~AmRtpPacket() 59 { 60 } 61 62 void AmRtpPacket::setAddr(struct sockaddr_storage* a) 63 { 64 memcpy(&addr,a,sizeof(sockaddr_storage)); 65 } 66 67 void AmRtpPacket::getAddr(struct sockaddr_storage* a) 68 { 69 memcpy(a,&addr,sizeof(sockaddr_storage)); 70 } 71 72 int AmRtpPacket::parse() 73 { 74 assert(buffer); 75 assert(b_size); 76 77 rtp_hdr_t* hdr = (rtp_hdr_t*)buffer; 78 // ZRTP "Hello" packet has version == 0 79 if ((hdr->version != RTP_VERSION) && (hdr->version != 0)) 80 { 81 DBG("received RTP packet with unsupported version (%i).\n", 82 hdr->version); 83 return -1; 84 } 85 86 data_offset = sizeof(rtp_hdr_t) + (hdr->cc*4); 87 88 if(hdr->x != 0) { 89 //#ifndef WITH_ZRTP 90 //if (AmConfig::IgnoreRTPXHdrs) { 91 // skip the extension header 92 //#endif 93 if (b_size >= data_offset + 4) { 94 data_offset += 95 ntohs(((rtp_xhdr_t*) (buffer + data_offset))->len)*4; 96 } 97 // #ifndef WITH_ZRTP 98 // } else { 99 // DBG("RTP extension headers not supported.\n"); 100 // return -1; 101 // } 102 // #endif 103 } 104 105 payload = hdr->pt; 106 marker = hdr->m; 107 sequence = ntohs(hdr->seq); 108 timestamp = ntohl(hdr->ts); 109 ssrc = ntohl(hdr->ssrc); 110 version = hdr->version; 111 112 if (data_offset > b_size) { 113 ERROR("bad rtp packet (hdr-size=%u;pkt-size=%u) !\n", 114 data_offset,b_size); 115 return -1; 116 } 117 d_size = b_size - data_offset; 118 119 if(hdr->p){ 120 if (buffer[b_size-1]>=d_size){ 121 ERROR("bad rtp packet (invalid padding size) !\n"); 122 return -1; 123 } 124 d_size -= buffer[b_size-1]; 125 } 126 127 return 0; 128 } 129 130 unsigned char *AmRtpPacket::getData() 131 { 132 return &buffer[data_offset]; 133 } 134 135 unsigned char *AmRtpPacket::getBuffer() 136 { 137 return &buffer[0]; 138 } 139 140 int AmRtpPacket::compile(unsigned char* data_buf, unsigned int size) 141 { 142 assert(data_buf); 143 assert(size); 144 145 d_size = size; 146 b_size = d_size + sizeof(rtp_hdr_t); 147 assert(b_size <= 4096); 148 rtp_hdr_t* hdr = (rtp_hdr_t*)buffer; 149 150 if(b_size>sizeof(buffer)){ 151 ERROR("builtin buffer size (%d) exceeded: %d\n", 152 (int)sizeof(buffer), b_size); 153 return -1; 154 } 155 156 memset(hdr,0,sizeof(rtp_hdr_t)); 157 hdr->version = RTP_VERSION; 158 hdr->m = marker; 159 hdr->pt = payload; 160 161 hdr->seq = htons(sequence); 162 hdr->ts = htonl(timestamp); 163 hdr->ssrc = htonl(ssrc); 164 165 data_offset = sizeof(rtp_hdr_t); 166 memcpy(&buffer[data_offset],data_buf,d_size); 167 168 return 0; 169 } 170 171 int AmRtpPacket::compile_raw(unsigned char* data_buf, unsigned int size) 172 { 173 if ((!size) || (!data_buf)) 174 return -1; 175 176 if(size>sizeof(buffer)){ 177 ERROR("builtin buffer size (%d) exceeded: %d\n", 178 (int)sizeof(buffer), size); 179 return -1; 180 } 181 182 memcpy(&buffer[0], data_buf, size); 183 b_size = size; 184 185 return size; 186 } 187 188 int AmRtpPacket::sendto(int sd) 189 { 190 int err = ::sendto(sd,buffer,b_size,0, 191 (const struct sockaddr *)&addr, 192 SA_len(&addr)); 193 194 if(err == -1){ 195 ERROR("while sending RTP packet: %s\n",strerror(errno)); 196 return -1; 197 } 198 199 return 0; 200 } 201 202 int AmRtpPacket::sendmsg(int sd, unsigned int sys_if_idx) 203 { 204 struct msghdr hdr; 205 struct cmsghdr* cmsg; 206 207 union { 208 #ifndef __FreeBSD__ 209 char cmsg4_buf[CMSG_SPACE(sizeof(struct in_pktinfo))]; 210 #endif 211 char cmsg6_buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; 212 } cmsg_buf; 213 214 struct iovec msg_iov[1]; 215 msg_iov[0].iov_base = (void*)buffer; 216 msg_iov[0].iov_len = b_size; 217 218 bzero(&hdr,sizeof(hdr)); 219 hdr.msg_name = (void*)&addr; 220 hdr.msg_namelen = SA_len(&addr); 221 hdr.msg_iov = msg_iov; 222 hdr.msg_iovlen = 1; 223 224 bzero(&cmsg_buf,sizeof(cmsg_buf)); 225 hdr.msg_control = &cmsg_buf; 226 hdr.msg_controllen = sizeof(cmsg_buf); 227 228 cmsg = CMSG_FIRSTHDR(&hdr); 229 if(addr.ss_family == AF_INET) { 230 #ifndef __FreeBSD__ 231 cmsg->cmsg_level = IPPROTO_IP; 232 cmsg->cmsg_type = IP_PKTINFO; 233 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 234 235 struct in_pktinfo* pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg); 236 pktinfo->ipi_ifindex = sys_if_idx; 237 #endif 238 } 239 else if(addr.ss_family == AF_INET6) { 240 cmsg->cmsg_level = IPPROTO_IPV6; 241 cmsg->cmsg_type = IPV6_PKTINFO; 242 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 243 244 struct in6_pktinfo* pktinfo = (struct in6_pktinfo*) CMSG_DATA(cmsg); 245 pktinfo->ipi6_ifindex = sys_if_idx; 246 } 247 248 hdr.msg_controllen = cmsg->cmsg_len; 249 250 // bytes_sent = ; 251 if(::sendmsg(sd, &hdr, 0) < 0) { 252 ERROR("sendto: %s\n",strerror(errno)); 253 return -1; 254 } 255 256 return 0; 257 } 258 259 int AmRtpPacket::send(int sd, unsigned int sys_if_idx, 260 sockaddr_storage* l_saddr, const std::string& rtp_mux_remote_ip, unsigned int rtp_mux_remote_port) 261 { 262 if (!rtp_mux_remote_ip.empty() && rtp_mux_remote_port) 263 return AmRtpMuxSender::instance()->send(buffer, b_size, rtp_mux_remote_ip, rtp_mux_remote_port, am_get_port(&addr)); 264 265 if(sys_if_idx && AmConfig::UseRawSockets) { 266 return raw_sender::send((char*)buffer,b_size,sys_if_idx,l_saddr,&addr); 267 } 268 269 if(sys_if_idx && AmConfig::ForceOutboundIf) { 270 return sendmsg(sd,sys_if_idx); 271 } 272 273 return sendto(sd); 274 } 275 276 int AmRtpPacket::recv(int sd) 277 { 278 socklen_t recv_addr_len = sizeof(struct sockaddr_storage); 279 int ret = recvfrom(sd,buffer,sizeof(buffer),0, 280 (struct sockaddr*)&addr, 281 &recv_addr_len); 282 283 if(ret > 0){ 284 285 if(ret > 4096) 286 return -1; 287 288 b_size = ret; 289 } 290 291 return ret; 292 } 293 294 int AmRtpPacket::recv(unsigned char* pkt, size_t len) 295 { 296 b_size = len > sizeof(buffer) ? sizeof(buffer) : len; 297 memcpy(buffer, pkt, b_size); 298 return b_size; 299 } 300 301 void AmRtpPacket::logReceived(msg_logger *logger, struct sockaddr_storage *laddr) 302 { 303 static const cstring empty; 304 logger->log((const char *)buffer, b_size, &addr, laddr, empty); 305 } 306 307 void AmRtpPacket::logSent(msg_logger *logger, struct sockaddr_storage *laddr) 308 { 309 static const cstring empty; 310 logger->log((const char *)buffer, b_size, laddr, &addr, empty); 311 } 312 313