00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "ortp/ortp.h"
00021 #include "utils.h"
00022 #include "ortp/rtpsession.h"
00023 #include "rtpsession_priv.h"
00024
00025
00026 #if defined(WIN32) || defined(_WIN32_WCE)
00027 #include "ortp-config-win32.h"
00028 #else
00029 #include "ortp-config.h"
00030 #endif
00031
00032 #ifdef HAVE_SYS_UIO_H
00033 #include <sys/uio.h>
00034 #define USE_SENDMSG 1
00035 #endif
00036
00037 #define can_connect(s) ( (s)->use_connect && !(s)->symmetric_rtp)
00038
00039 static bool_t try_connect(int fd, const struct sockaddr *dest, socklen_t addrlen){
00040 if (connect(fd,dest,addrlen)<0){
00041 ortp_warning("Could not connect() socket: %s",getSocketError());
00042 return FALSE;
00043 }
00044 return TRUE;
00045 }
00046
00047 static ortp_socket_t create_and_bind(const char *addr, int port, int *sock_family){
00048 int err;
00049 int optval = 1;
00050 ortp_socket_t sock=-1;
00051 #ifdef ORTP_INET6
00052 char num[8];
00053 struct addrinfo hints, *res0, *res;
00054 #else
00055 struct sockaddr_in saddr;
00056 #endif
00057
00058 #ifdef ORTP_INET6
00059
00060 memset(&hints, 0, sizeof(hints));
00061 hints.ai_family = PF_UNSPEC;
00062 hints.ai_socktype = SOCK_DGRAM;
00063 snprintf(num, sizeof(num), "%d",port);
00064 err = getaddrinfo(addr,num, &hints, &res0);
00065 if (err!=0) {
00066 ortp_warning ("Error in getaddrinfo on (addr=%s port=%i): %s", addr, port, gai_strerror(err));
00067 return -1;
00068 }
00069
00070 for (res = res0; res; res = res->ai_next) {
00071 sock = socket(res->ai_family, res->ai_socktype, 0);
00072 if (sock < 0)
00073 continue;
00074
00075 err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
00076 (SOCKET_OPTION_VALUE)&optval, sizeof (optval));
00077 if (err < 0)
00078 {
00079 ortp_warning ("Fail to set rtp address reusable: %s.", getSocketError());
00080 }
00081
00082 *sock_family=res->ai_family;
00083 err = bind (sock, res->ai_addr, res->ai_addrlen);
00084 if (err != 0)
00085 {
00086 ortp_warning ("Fail to bind rtp socket to (addr=%s port=%i) : %s.", addr,port, getSocketError());
00087 close_socket (sock);
00088 sock=-1;
00089 continue;
00090 }
00091 #ifndef __hpux
00092 switch (res->ai_family)
00093 {
00094 case AF_INET:
00095 if (IN_MULTICAST(ntohl(((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr)))
00096 {
00097 struct ip_mreq mreq;
00098 mreq.imr_multiaddr.s_addr = ((struct sockaddr_in *) res->ai_addr)->sin_addr.s_addr;
00099 mreq.imr_interface.s_addr = INADDR_ANY;
00100 err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (SOCKET_OPTION_VALUE) &mreq, sizeof(mreq));
00101 if (err < 0)
00102 {
00103 ortp_warning ("Fail to join address group: %s.", getSocketError());
00104 close_socket (sock);
00105 sock=-1;
00106 continue;
00107 }
00108 }
00109 break;
00110 case AF_INET6:
00111 if (IN6_IS_ADDR_MULTICAST(&(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr)))
00112 {
00113 struct ipv6_mreq mreq;
00114 mreq.ipv6mr_multiaddr = ((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
00115 mreq.ipv6mr_interface = 0;
00116 err = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (SOCKET_OPTION_VALUE)&mreq, sizeof(mreq));
00117 if (err < 0)
00118 {
00119 ortp_warning ("Fail to join address group: %s.", getSocketError());
00120 close_socket (sock);
00121 sock=-1;
00122 continue;
00123 }
00124 }
00125 break;
00126 }
00127 #endif
00128 break;
00129 }
00130 freeaddrinfo(res0);
00131 #else
00132 saddr.sin_family = AF_INET;
00133 *sock_family=AF_INET;
00134 err = inet_aton (addr, &saddr.sin_addr);
00135 if (err < 0)
00136 {
00137 ortp_warning ("Error in socket address:%s.", getSocketError());
00138 return err;
00139 }
00140 saddr.sin_port = htons (port);
00141
00142 sock = socket (PF_INET, SOCK_DGRAM, 0);
00143
00144 if (sock<0) return -1;
00145
00146 err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
00147 (SOCKET_OPTION_VALUE)&optval, sizeof (optval));
00148 if (err < 0)
00149 {
00150 ortp_warning ("Fail to set rtp address reusable: %s.",getSocketError());
00151 }
00152
00153 err = bind (sock,
00154 (struct sockaddr *) &saddr,
00155 sizeof (saddr));
00156
00157 if (err != 0)
00158 {
00159 ortp_warning ("Fail to bind rtp socket to port %i: %s.", port, getSocketError());
00160 close_socket (sock);
00161 return -1;
00162 }
00163 #endif
00164 if (sock>=0)
00165 {
00166 #ifdef WIN32
00167
00168 int bufsize = 32768;
00169 err = setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void *)&bufsize, sizeof(bufsize));
00170 if (err == -1) {
00171 ortp_warning ("Fail to increase buffer size for socket (port %i): %s.", port, getSocketError());
00172 }
00173 bufsize = 32768;
00174 err = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void *)&bufsize, sizeof(bufsize));
00175 if (err == -1) {
00176 ortp_warning ("Fail to increase buffer size for socket (port %i): %s.", port, getSocketError());
00177 }
00178 #endif
00179 set_non_blocking_socket (sock);
00180 }
00181 return sock;
00182 }
00183
00184 static ortp_socket_t create_and_bind_random(const char *localip, int *sock_family, int *port){
00185 int retry;
00186 ortp_socket_t sock = -1;
00187 for (retry=0;retry<100;retry++)
00188 {
00189 int localport;
00190 do
00191 {
00192 localport = (rand () + 5000) & 0xfffe;
00193 }
00194 while ((localport < 5000) || (localport > 0xffff));
00195 sock = create_and_bind(localip, localport, sock_family);
00196 if (sock>=0) {
00197 *port=localport;
00198 return sock;
00199 }
00200 }
00201 ortp_warning("create_and_bind_random: Could not find a random port for %s !",localip);
00202 return -1;
00203 }
00204
00220 int
00221 rtp_session_set_local_addr (RtpSession * session, const char * addr, int port)
00222 {
00223 ortp_socket_t sock;
00224 int sockfamily;
00225 if (session->rtp.socket>=0){
00226
00227 rtp_session_release_sockets(session);
00228 }
00229
00230 if (port>0)
00231 sock=create_and_bind(addr,port,&sockfamily);
00232 else
00233 sock=create_and_bind_random(addr,&sockfamily,&port);
00234 if (sock>=0){
00235 session->rtp.sockfamily=sockfamily;
00236 session->rtp.socket=sock;
00237 session->rtp.loc_port=port;
00238
00239 sock=create_and_bind(addr,port+1,&sockfamily);
00240 if (sock>=0){
00241 session->rtcp.sockfamily=sockfamily;
00242 session->rtcp.socket=sock;
00243 }else{
00244 ortp_warning("Could not create and bind rtcp socket.");
00245 }
00246
00247
00248 rtp_session_set_dscp( session, -1 );
00249 rtp_session_set_multicast_ttl( session, -1 );
00250 rtp_session_set_multicast_loopback( session, -1 );
00251
00252 return 0;
00253 }
00254 return -1;
00255 }
00256
00257
00268 int rtp_session_set_multicast_ttl(RtpSession *session, int ttl)
00269 {
00270 int retval;
00271
00272
00273 if (ttl>0) session->multicast_ttl = ttl;
00274
00275
00276 if (session->rtp.socket < 0) return 0;
00277
00278 switch (session->rtp.sockfamily) {
00279 case AF_INET: {
00280
00281 retval= setsockopt(session->rtp.socket, IPPROTO_IP, IP_MULTICAST_TTL,
00282 (SOCKET_OPTION_VALUE) &session->multicast_ttl, sizeof(session->multicast_ttl));
00283
00284 if (retval<0) break;
00285
00286 retval= setsockopt(session->rtcp.socket, IPPROTO_IP, IP_MULTICAST_TTL,
00287 (SOCKET_OPTION_VALUE) &session->multicast_ttl, sizeof(session->multicast_ttl));
00288
00289 } break;
00290
00291 case AF_INET6: {
00292
00293 retval= setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
00294 (SOCKET_OPTION_VALUE)&session->multicast_ttl, sizeof(session->multicast_ttl));
00295
00296 if (retval<0) break;
00297
00298 retval= setsockopt(session->rtcp.socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
00299 (SOCKET_OPTION_VALUE) &session->multicast_ttl, sizeof(session->multicast_ttl));
00300
00301 } break;
00302
00303 default:
00304 retval=-1;
00305 }
00306
00307 if (retval<0)
00308 ortp_warning("Failed to set multicast TTL on socket.");
00309
00310
00311 return retval;
00312 }
00313
00314
00322 int rtp_session_get_multicast_ttl(RtpSession *session)
00323 {
00324 return session->multicast_ttl;
00325 }
00326
00327
00338 int rtp_session_set_multicast_loopback(RtpSession *session, int yesno)
00339 {
00340 int retval;
00341
00342
00343 if (yesno==0) {
00344
00345 session->multicast_loopback = 0;
00346 } else if (yesno>0) {
00347
00348 session->multicast_loopback = 1;
00349 }
00350
00351
00352 if (session->rtp.socket < 0) return 0;
00353
00354 switch (session->rtp.sockfamily) {
00355 case AF_INET: {
00356
00357 retval= setsockopt(session->rtp.socket, IPPROTO_IP, IP_MULTICAST_LOOP,
00358 (SOCKET_OPTION_VALUE) &session->multicast_loopback, sizeof(session->multicast_loopback));
00359
00360 if (retval<0) break;
00361
00362 retval= setsockopt(session->rtcp.socket, IPPROTO_IP, IP_MULTICAST_LOOP,
00363 (SOCKET_OPTION_VALUE) &session->multicast_loopback, sizeof(session->multicast_loopback));
00364
00365 } break;
00366
00367 case AF_INET6: {
00368
00369 retval= setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
00370 (SOCKET_OPTION_VALUE) &session->multicast_loopback, sizeof(session->multicast_loopback));
00371
00372 if (retval<0) break;
00373
00374 retval= setsockopt(session->rtcp.socket, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
00375 (SOCKET_OPTION_VALUE) &session->multicast_loopback, sizeof(session->multicast_loopback));
00376
00377 } break;
00378
00379 default:
00380 retval=-1;
00381 }
00382
00383 if (retval<0)
00384 ortp_warning("Failed to set multicast loopback on socket.");
00385
00386
00387 return retval;
00388 }
00389
00390
00398 int rtp_session_get_multicast_loopback(RtpSession *session)
00399 {
00400 return session->multicast_loopback;
00401 }
00402
00413 int rtp_session_set_dscp(RtpSession *session, int dscp){
00414 int retval=0;
00415 int tos;
00416
00417
00418 if (dscp>=0) session->dscp = dscp;
00419
00420
00421 if (session->rtp.socket < 0) return 0;
00422
00423
00424 tos = (session->dscp << 2) & 0xFC;
00425 switch (session->rtp.sockfamily) {
00426 case AF_INET:
00427 retval = setsockopt(session->rtp.socket, IPPROTO_IP, IP_TOS, (SOCKET_OPTION_VALUE)&tos, sizeof(tos));
00428 break;
00429 #ifdef ORTP_INET6
00430 case AF_INET6:
00431 # ifdef IPV6_TCLASS
00432 retval = setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_TCLASS,
00433 (SOCKET_OPTION_VALUE)&tos, sizeof(tos));
00434 # else
00435
00436 retval = setsockopt(session->rtp.socket, IPPROTO_IPV6, IP_TOS,
00437 (SOCKET_OPTION_VALUE)&tos, sizeof(tos));
00438 #endif
00439 break;
00440 #endif
00441 default:
00442 retval=-1;
00443 }
00444 if (retval<0)
00445 ortp_warning("Failed to set DSCP value on socket.");
00446
00447 return retval;
00448 }
00449
00450
00458 int rtp_session_get_dscp(const RtpSession *session)
00459 {
00460 return session->dscp;
00461 }
00462
00463
00474 int rtp_session_get_local_port(const RtpSession *session){
00475 return (session->rtp.loc_port>0) ? session->rtp.loc_port : -1;
00476 }
00477
00478
00479 static char * ortp_inet_ntoa(struct sockaddr *addr, int addrlen, char *dest, int destlen){
00480 #ifdef ORTP_INET6
00481 int err;
00482 dest[0]=0;
00483 err=getnameinfo(addr,addrlen,dest,destlen,NULL,0,NI_NUMERICHOST);
00484 if (err!=0){
00485 ortp_warning("getnameinfo error: %s",gai_strerror(err));
00486 }
00487 #else
00488 char *tmp=inet_ntoa(((struct sockaddr_in*)addr)->sin_addr);
00489 strncpy(dest,tmp,destlen);
00490 dest[destlen-1]='\0';
00491 #endif
00492 return dest;
00493 }
00494
00508 int
00509 rtp_session_set_remote_addr (RtpSession * session, const char * addr, int port)
00510 {
00511 int err;
00512 #ifdef ORTP_INET6
00513 struct addrinfo hints, *res0, *res;
00514 char num[8];
00515 memset(&hints, 0, sizeof(hints));
00516 hints.ai_family = PF_UNSPEC;
00517 hints.ai_socktype = SOCK_DGRAM;
00518 snprintf(num, sizeof(num), "%d", port);
00519 err = getaddrinfo(addr, num, &hints, &res0);
00520 if (err) {
00521 ortp_warning ("Error in socket address: %s", gai_strerror(err));
00522 return -1;
00523 }
00524 #endif
00525 if (session->rtp.socket == -1){
00526
00527 ortp_message ("Setting random local addresses.");
00528 #ifdef ORTP_INET6
00529
00530 if (res0->ai_addr->sa_family==AF_INET6)
00531 err = rtp_session_set_local_addr (session, "::", -1);
00532 else err=rtp_session_set_local_addr (session, "0.0.0.0", -1);
00533 #else
00534 err = rtp_session_set_local_addr (session, "0.0.0.0", -1);
00535 #endif
00536 if (err<0) return -1;
00537 }
00538
00539 #ifdef ORTP_INET6
00540 err=1;
00541 for (res = res0; res; res = res->ai_next) {
00542
00543 if (res->ai_family==session->rtp.sockfamily ) {
00544 memcpy( &session->rtp.rem_addr, res->ai_addr, res->ai_addrlen);
00545 session->rtp.rem_addrlen=res->ai_addrlen;
00546 err=0;
00547 break;
00548 }
00549 }
00550 freeaddrinfo(res0);
00551 if (err) {
00552 ortp_warning("Could not set destination for RTP socket to %s:%i.",addr,port);
00553 return -1;
00554 }
00555
00556 memset(&hints, 0, sizeof(hints));
00557 hints.ai_family = PF_UNSPEC;
00558 hints.ai_socktype = SOCK_DGRAM;
00559 snprintf(num, sizeof(num), "%d", (port + 1));
00560 err = getaddrinfo(addr, num, &hints, &res0);
00561 if (err) {
00562 ortp_warning ("Error: %s", gai_strerror(err));
00563 return err;
00564 }
00565 err=1;
00566 for (res = res0; res; res = res->ai_next) {
00567
00568 if (res->ai_family==session->rtp.sockfamily ) {
00569 err=0;
00570 memcpy( &session->rtcp.rem_addr, res->ai_addr, res->ai_addrlen);
00571 session->rtcp.rem_addrlen=res->ai_addrlen;
00572 break;
00573 }
00574 }
00575 freeaddrinfo(res0);
00576 if (err) {
00577 ortp_warning("Could not set destination for RCTP socket to %s:%i.",addr,port+1);
00578 return -1;
00579 }
00580 #else
00581 session->rtp.rem_addrlen=sizeof(session->rtp.rem_addr);
00582 session->rtp.rem_addr.sin_family = AF_INET;
00583
00584 err = inet_aton (addr, &session->rtp.rem_addr.sin_addr);
00585 if (err < 0)
00586 {
00587 ortp_warning ("Error in socket address:%s.", getSocketError());
00588 return err;
00589 }
00590 session->rtp.rem_addr.sin_port = htons (port);
00591
00592 memcpy (&session->rtcp.rem_addr, &session->rtp.rem_addr,
00593 sizeof (struct sockaddr_in));
00594 session->rtcp.rem_addr.sin_port = htons (port + 1);
00595 session->rtcp.rem_addrlen=sizeof(session->rtcp.rem_addr);
00596 #endif
00597 if (can_connect(session)){
00598 if (try_connect(session->rtp.socket,(struct sockaddr*)&session->rtp.rem_addr,session->rtp.rem_addrlen))
00599 session->flags|=RTP_SOCKET_CONNECTED;
00600 if (session->rtcp.socket>=0){
00601 if (try_connect(session->rtcp.socket,(struct sockaddr*)&session->rtcp.rem_addr,session->rtcp.rem_addrlen))
00602 session->flags|=RTCP_SOCKET_CONNECTED;
00603 }
00604 }else if (session->flags & RTP_SOCKET_CONNECTED){
00605
00606
00607 struct sockaddr sa;
00608 sa.sa_family=AF_UNSPEC;
00609 if (connect(session->rtp.socket,&sa,sizeof(sa))<0){
00610 ortp_error("Cannot dissolve connect() association for rtp socket: %s", getSocketError());
00611 }
00612 if (connect(session->rtcp.socket,&sa,sizeof(sa))<0){
00613 ortp_error("Cannot dissolve connect() association for rtcp socket: %s", getSocketError());
00614 }
00615 session->flags&=~RTP_SOCKET_CONNECTED;
00616 session->flags&=~RTCP_SOCKET_CONNECTED;
00617 }
00618 return 0;
00619 }
00620
00621 void rtp_session_set_sockets(RtpSession *session, int rtpfd, int rtcpfd)
00622 {
00623 if (rtpfd>=0) set_non_blocking_socket(rtpfd);
00624 if (rtcpfd>=0) set_non_blocking_socket(rtcpfd);
00625 session->rtp.socket=rtpfd;
00626 session->rtcp.socket=rtcpfd;
00627 if (rtpfd>=0 || rtcpfd>=0 )
00628 session->flags|=(RTP_SESSION_USING_EXT_SOCKETS|RTP_SOCKET_CONNECTED|RTCP_SOCKET_CONNECTED);
00629 else session->flags&=~(RTP_SESSION_USING_EXT_SOCKETS|RTP_SOCKET_CONNECTED|RTCP_SOCKET_CONNECTED);
00630 }
00631
00632 void rtp_session_set_transports(RtpSession *session, struct _RtpTransport *rtptr, struct _RtpTransport *rtcptr)
00633 {
00634 session->rtp.tr = rtptr;
00635 session->rtcp.tr = rtcptr;
00636 if (rtptr || rtcptr )
00637 session->flags|=(RTP_SESSION_USING_TRANSPORT);
00638 else session->flags&=~(RTP_SESSION_USING_TRANSPORT);
00639 }
00640
00641
00642
00653 void rtp_session_flush_sockets(RtpSession *session){
00654 char trash[4096];
00655 #ifdef ORTP_INET6
00656 struct sockaddr_storage from;
00657 #else
00658 struct sockaddr from;
00659 #endif
00660 socklen_t fromlen=sizeof(from);
00661 if (rtp_session_using_transport(session, rtp))
00662 {
00663 while (session->rtp.tr->t_recvfrom(session->rtp.tr,trash,sizeof(trash),0,(struct sockaddr *)&from,&fromlen)>0){};
00664
00665 if (session->rtcp.tr)
00666 while (session->rtcp.tr->t_recvfrom(session->rtcp.tr,trash,sizeof(trash),0,(struct sockaddr *)&from,&fromlen)>0){};
00667
00668 return;
00669 }
00670
00671 if (session->rtp.socket>=0){
00672 while (recvfrom(session->rtp.socket,trash,sizeof(trash),0,(struct sockaddr *)&from,&fromlen)>0){};
00673 }
00674 if (session->rtcp.socket>=0){
00675 while (recvfrom(session->rtcp.socket,trash,sizeof(trash),0,(struct sockaddr*)&from,&fromlen)>0){};
00676 }
00677 }
00678
00679
00680 #ifdef USE_SENDMSG
00681 #define MAX_IOV 30
00682 static int rtp_sendmsg(int sock,mblk_t *m, struct sockaddr *rem_addr, int addr_len){
00683 int error;
00684 struct msghdr msg;
00685 struct iovec iov[MAX_IOV];
00686 int iovlen;
00687 for(iovlen=0; iovlen<MAX_IOV && m!=NULL; m=m->b_cont,iovlen++){
00688 iov[iovlen].iov_base=m->b_rptr;
00689 iov[iovlen].iov_len=m->b_wptr-m->b_rptr;
00690 }
00691 if (iovlen==MAX_IOV){
00692 ortp_error("Too long msgb, didn't fit into iov, end discarded.");
00693 }
00694 msg.msg_name=(void*)rem_addr;
00695 msg.msg_namelen=addr_len;
00696 msg.msg_iov=&iov[0];
00697 msg.msg_iovlen=iovlen;
00698 msg.msg_control=NULL;
00699 msg.msg_controllen=0;
00700 msg.msg_flags=0;
00701 error=sendmsg(sock,&msg,0);
00702 return error;
00703 }
00704 #endif
00705
00706 #define IP_UDP_OVERHEAD (20+8)
00707
00708 static void update_sent_bytes(RtpSession*s, int nbytes){
00709 if (s->rtp.sent_bytes==0){
00710 gettimeofday(&s->rtp.send_bw_start,NULL);
00711 }
00712 s->rtp.sent_bytes+=nbytes+IP_UDP_OVERHEAD;
00713 }
00714
00715 static void update_recv_bytes(RtpSession*s, int nbytes){
00716 if (s->rtp.recv_bytes==0){
00717 gettimeofday(&s->rtp.recv_bw_start,NULL);
00718 }
00719 s->rtp.recv_bytes+=nbytes+IP_UDP_OVERHEAD;
00720 }
00721
00722 int
00723 rtp_session_rtp_send (RtpSession * session, mblk_t * m)
00724 {
00725 int error;
00726 int i;
00727 rtp_header_t *hdr;
00728 struct sockaddr *destaddr=(struct sockaddr*)&session->rtp.rem_addr;
00729 socklen_t destlen=session->rtp.rem_addrlen;
00730 ortp_socket_t sockfd=session->rtp.socket;
00731
00732 hdr = (rtp_header_t *) m->b_rptr;
00733
00734 hdr->ssrc = htonl (hdr->ssrc);
00735 hdr->timestamp = htonl (hdr->timestamp);
00736 hdr->seq_number = htons (hdr->seq_number);
00737 for (i = 0; i < hdr->cc; i++)
00738 hdr->csrc[i] = htonl (hdr->csrc[i]);
00739
00740 if (session->flags & RTP_SOCKET_CONNECTED) {
00741 destaddr=NULL;
00742 destlen=0;
00743 }
00744 #ifdef USE_SENDMSG
00745 error=rtp_sendmsg(sockfd,m,destaddr,destlen);
00746 #else
00747 if (m->b_cont!=NULL){
00748 msgpullup(m,-1);
00749 }
00750
00751 if (rtp_session_using_transport(session, rtp))
00752 error = (session->rtp.tr->t_sendto) (session->rtp.tr, m->b_rptr, (int) (m->b_wptr - m->b_rptr),
00753 0,destaddr,destlen);
00754 else
00755 error = sendto (sockfd, m->b_rptr, (int) (m->b_wptr - m->b_rptr),
00756 0,destaddr,destlen);
00757 #endif
00758 if (error < 0){
00759 if (session->on_network_error.count>0){
00760 rtp_signal_table_emit3(&session->on_network_error,(long)"Error sending RTP packet",INT_TO_POINTER(getSocketErrorCode()));
00761 }else ortp_warning ("Error sending rtp packet: %s ; socket=%i", getSocketError(), sockfd);
00762 }else{
00763 update_sent_bytes(session,error);
00764 }
00765 freemsg (m);
00766 return error;
00767 }
00768
00769 int
00770 rtp_session_rtcp_send (RtpSession * session, mblk_t * m)
00771 {
00772 int error=0;
00773 ortp_socket_t sockfd=session->rtcp.socket;
00774 struct sockaddr *destaddr=(struct sockaddr*)&session->rtcp.rem_addr;
00775 socklen_t destlen=session->rtcp.rem_addrlen;
00776 bool_t using_connected_socket=(session->flags & RTCP_SOCKET_CONNECTED)!=0;
00777
00778 if (using_connected_socket) {
00779 destaddr=NULL;
00780 destlen=0;
00781 }
00782
00783 if ((sockfd>=0 || rtp_session_using_transport(session, rtcp)) && (session->rtcp.rem_addrlen>0 ||using_connected_socket) ){
00784
00785 #ifndef USE_SENDMSG
00786 if (m->b_cont!=NULL){
00787 msgpullup(m,-1);
00788 }
00789 if (rtp_session_using_transport(session, rtcp))
00790 error = (session->rtcp.tr->t_sendto) (session->rtcp.tr, m->b_rptr,
00791 (int) (m->b_wptr - m->b_rptr), 0,
00792 destaddr, destlen);
00793 else
00794 error = sendto (sockfd, m->b_rptr,
00795 (int) (m->b_wptr - m->b_rptr), 0,
00796 destaddr, destlen);
00797 #else
00798 error=rtp_sendmsg(sockfd,m,destaddr, destlen);
00799 #endif
00800 if (error < 0){
00801 char host[50];
00802 if (session->on_network_error.count>0){
00803 rtp_signal_table_emit3(&session->on_network_error,(long)"Error sending RTCP packet",INT_TO_POINTER(getSocketErrorCode()));
00804 }else ortp_warning ("Error sending rtcp packet: %s ; socket=%i; addr=%s", getSocketError(), session->rtcp.socket, ortp_inet_ntoa((struct sockaddr*)&session->rtcp.rem_addr,session->rtcp.rem_addrlen,host,sizeof(host)) );
00805 }
00806 }else ortp_warning("Cannot send rtcp report: sockfd=%i, rem_addrlen=%i, connected=%i",sockfd,session->rtcp.rem_addrlen,using_connected_socket);
00807 freemsg (m);
00808 return error;
00809 }
00810
00811 int
00812 rtp_session_rtp_recv (RtpSession * session, uint32_t user_ts)
00813 {
00814 int error;
00815 ortp_socket_t sockfd=session->rtp.socket;
00816 #ifdef ORTP_INET6
00817 struct sockaddr_storage remaddr;
00818 #else
00819 struct sockaddr remaddr;
00820 #endif
00821 socklen_t addrlen = sizeof (remaddr);
00822 mblk_t *mp;
00823
00824 if ((sockfd<0) && !rtp_session_using_transport(session, rtp)) return -1;
00825
00826 while (1)
00827 {
00828 int bufsz;
00829 bool_t sock_connected=!!(session->flags & RTP_SOCKET_CONNECTED);
00830
00831 if (session->rtp.cached_mp==NULL)
00832 session->rtp.cached_mp = allocb (session->recv_buf_size, 0);
00833 mp=session->rtp.cached_mp;
00834 bufsz=(int) (mp->b_datap->db_lim - mp->b_datap->db_base);
00835 if (sock_connected){
00836 error=recv(sockfd,mp->b_wptr,bufsz,0);
00837 }else if (rtp_session_using_transport(session, rtp))
00838 error = (session->rtp.tr->t_recvfrom)(session->rtp.tr, mp->b_wptr,
00839 bufsz, 0,
00840 (struct sockaddr *) &remaddr,
00841 &addrlen);
00842 else error = recvfrom(sockfd, mp->b_wptr,
00843 bufsz, 0,
00844 (struct sockaddr *) &remaddr,
00845 &addrlen);
00846 if (error > 0){
00847 if (session->symmetric_rtp && !sock_connected){
00848
00849 memcpy(&session->rtp.rem_addr,&remaddr,addrlen);
00850 session->rtp.rem_addrlen=addrlen;
00851 if (session->use_connect){
00852 if (try_connect(sockfd,(struct sockaddr*)&remaddr,addrlen))
00853 session->flags|=RTP_SOCKET_CONNECTED;
00854 }
00855 }
00856
00857 mp->b_wptr+=error;
00858 rtp_session_rtp_parse (session, mp, user_ts + session->rtp.hwrcv_diff_ts, (struct sockaddr*)&remaddr,addrlen);
00859 session->rtp.cached_mp=NULL;
00860
00861 update_recv_bytes(session,error);
00862 }
00863 else
00864 {
00865 int errnum=getSocketErrorCode();
00866
00867 if (error == 0)
00868 {
00869 ortp_warning
00870 ("rtp_recv: strange... recv() returned zero.");
00871 }
00872 else if (!is_would_block_error(errnum))
00873 {
00874 if (session->on_network_error.count>0){
00875 rtp_signal_table_emit3(&session->on_network_error,(long)"Error receiving RTP packet",INT_TO_POINTER(getSocketErrorCode()));
00876 }else ortp_warning("Error receiving RTP packet: %s.",getSocketError());
00877 }
00878
00879 return -1;
00880 }
00881 }
00882 return error;
00883 }
00884
00885 void rtp_session_notify_inc_rtcp(RtpSession *session, mblk_t *m){
00886 if (session->eventqs!=NULL){
00887 OrtpEvent *ev=ortp_event_new(ORTP_EVENT_RTCP_PACKET_RECEIVED);
00888 OrtpEventData *d=ortp_event_get_data(ev);
00889 d->packet=m;
00890 rtp_session_dispatch_event(session,ev);
00891 }
00892 else
00893 freemsg(m);
00894 }
00895
00896 int
00897 rtp_session_rtcp_recv (RtpSession * session)
00898 {
00899 int error;
00900 #ifdef ORTP_INET6
00901 struct sockaddr_storage remaddr;
00902 #else
00903 struct sockaddr remaddr;
00904 #endif
00905 socklen_t addrlen=0;
00906 mblk_t *mp;
00907
00908 if (session->rtcp.socket<0 && !rtp_session_using_transport(session, rtcp)) return -1;
00909
00910
00911 while (1)
00912 {
00913 bool_t sock_connected=!!(session->flags & RTCP_SOCKET_CONNECTED);
00914 if (session->rtcp.cached_mp==NULL)
00915 session->rtcp.cached_mp = allocb (RTCP_MAX_RECV_BUFSIZE, 0);
00916
00917 mp=session->rtcp.cached_mp;
00918 if (sock_connected){
00919 error=recv(session->rtcp.socket,mp->b_wptr,RTCP_MAX_RECV_BUFSIZE,0);
00920 }else {
00921 addrlen=sizeof (remaddr);
00922
00923 if (rtp_session_using_transport(session, rtcp))
00924 error=(session->rtcp.tr->t_recvfrom)(session->rtcp.tr, mp->b_wptr,
00925 RTCP_MAX_RECV_BUFSIZE, 0,
00926 (struct sockaddr *) &remaddr,
00927 &addrlen);
00928 else
00929 error=recvfrom (session->rtcp.socket, mp->b_wptr,
00930 RTCP_MAX_RECV_BUFSIZE, 0,
00931 (struct sockaddr *) &remaddr,
00932 &addrlen);
00933 }
00934 if (error > 0)
00935 {
00936 mp->b_wptr += error;
00937
00938 {
00939 rtp_session_notify_inc_rtcp(session,mp);
00940 }
00941 session->rtcp.cached_mp=NULL;
00942 if (session->symmetric_rtp && !sock_connected){
00943
00944 memcpy(&session->rtcp.rem_addr,&remaddr,addrlen);
00945 session->rtcp.rem_addrlen=addrlen;
00946 if (session->use_connect){
00947 if (try_connect(session->rtcp.socket,(struct sockaddr*)&remaddr,addrlen))
00948 session->flags|=RTCP_SOCKET_CONNECTED;
00949 }
00950 }
00951 }
00952 else
00953 {
00954 int errnum=getSocketErrorCode();
00955
00956 if (error == 0)
00957 {
00958 ortp_warning
00959 ("rtcp_recv: strange... recv() returned zero.");
00960 }
00961 else if (!is_would_block_error(errnum))
00962 {
00963 if (session->on_network_error.count>0){
00964 rtp_signal_table_emit3(&session->on_network_error,(long)"Error receiving RTCP packet",INT_TO_POINTER(errnum));
00965 }else ortp_warning("Error receiving RTCP packet: %s.",getSocketError());
00966 }
00967
00968 return -1;
00969 }
00970 }
00971 return error;
00972 }
00973