src/rtpsession_inet.c

00001 /*
00002   The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.
00003   Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Lesser General Public
00007   License as published by the Free Software Foundation; either
00008   version 2.1 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Lesser General Public License for more details.
00014 
00015   You should have received a copy of the GNU Lesser General Public
00016   License along with this library; if not, write to the Free Software
00017   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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" /*needed for HAVE_SYS_UIO_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 /*hpux*/
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                 /* increase RTP buffer on windows */
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                 /* don't rebind, but close before*/
00227                 rtp_session_release_sockets(session);
00228         }
00229         /* try to bind the rtp port */
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                 /*try to bind rtcp port */
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                 /* set socket options (but don't change chosen states) */
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     // Store new TTL if one is specified
00273     if (ttl>0) session->multicast_ttl = ttl;
00274     
00275     // Don't do anything if socket hasn't been created yet
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     // Store new loopback state if one is specified
00343     if (yesno==0) {
00344         // Don't loop back
00345         session->multicast_loopback = 0;
00346     } else if (yesno>0) {
00347         // Do loop back
00348         session->multicast_loopback = 1;
00349     }
00350      
00351     // Don't do anything if socket hasn't been created yet
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         // Store new DSCP value if one is specified
00418         if (dscp>=0) session->dscp = dscp;
00419         
00420         // Don't do anything if socket hasn't been created yet
00421         if (session->rtp.socket < 0) return 0;
00422 
00423         // DSCP value is in the upper six bits of the TOS field
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 /*seems not defined by my libc*/
00432                 retval = setsockopt(session->rtp.socket, IPPROTO_IPV6, IPV6_TCLASS,
00433                  (SOCKET_OPTION_VALUE)&tos, sizeof(tos));
00434 #       else
00435                 /*in case that works:*/
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 
00507 int
00508 rtp_session_set_remote_addr (RtpSession * session, const char * addr, int port)
00509 {
00510   return rtp_session_set_remote_addr_and_port (session, addr, port, port+1);
00511 }
00512 
00527 int
00528 rtp_session_set_remote_addr_and_port (RtpSession * session, const char * addr, int rtp_port, int rtcp_port)
00529 {
00530         int err;
00531 #ifdef ORTP_INET6
00532         struct addrinfo hints, *res0, *res;
00533         char num[8];
00534         memset(&hints, 0, sizeof(hints));
00535         hints.ai_family = PF_UNSPEC;
00536         hints.ai_socktype = SOCK_DGRAM;
00537         snprintf(num, sizeof(num), "%d", rtp_port);
00538         err = getaddrinfo(addr, num, &hints, &res0);
00539         if (err) {
00540                 ortp_warning ("Error in socket address: %s", gai_strerror(err));
00541                 return -1;
00542         }
00543 #endif
00544         if (session->rtp.socket == -1){
00545                 /* the session has not its socket bound, do it */
00546                 ortp_message ("Setting random local addresses.");
00547 #ifdef ORTP_INET6
00548                 /* bind to an address type that matches the destination address */
00549                 if (res0->ai_addr->sa_family==AF_INET6)
00550                         err = rtp_session_set_local_addr (session, "::", -1);
00551                 else err=rtp_session_set_local_addr (session, "0.0.0.0", -1);
00552 #else
00553                 err = rtp_session_set_local_addr (session, "0.0.0.0", -1);
00554 #endif
00555                 if (err<0) return -1;
00556         }
00557 
00558 #ifdef ORTP_INET6
00559         err=1;
00560         for (res = res0; res; res = res->ai_next) {
00561                 /* set a destination address that has the same type as the local address */
00562                 if (res->ai_family==session->rtp.sockfamily ) {
00563                         memcpy( &session->rtp.rem_addr, res->ai_addr, res->ai_addrlen);
00564                         session->rtp.rem_addrlen=res->ai_addrlen;
00565                         err=0;
00566                         break;
00567                 }
00568         }
00569         freeaddrinfo(res0);
00570         if (err) {
00571                 ortp_warning("Could not set destination for RTP socket to %s:%i.",addr,rtp_port);
00572                 return -1;
00573         }
00574         
00575         memset(&hints, 0, sizeof(hints));
00576         hints.ai_family = PF_UNSPEC;
00577         hints.ai_socktype = SOCK_DGRAM;
00578         snprintf(num, sizeof(num), "%d", rtcp_port);
00579         err = getaddrinfo(addr, num, &hints, &res0);
00580         if (err) {
00581                 ortp_warning ("Error: %s", gai_strerror(err));
00582                 return err;
00583         }
00584         err=1;
00585         for (res = res0; res; res = res->ai_next) {
00586                 /* set a destination address that has the same type as the local address */
00587                 if (res->ai_family==session->rtp.sockfamily ) {
00588                         err=0;
00589                         memcpy( &session->rtcp.rem_addr, res->ai_addr, res->ai_addrlen);
00590                         session->rtcp.rem_addrlen=res->ai_addrlen;
00591                         break;
00592                 }
00593         }
00594         freeaddrinfo(res0);
00595         if (err) {
00596                 ortp_warning("Could not set destination for RCTP socket to %s:%i.",addr,rtcp_port);
00597                 return -1;
00598         }
00599 #else
00600         session->rtp.rem_addrlen=sizeof(session->rtp.rem_addr);
00601         session->rtp.rem_addr.sin_family = AF_INET;
00602 
00603         err = inet_aton (addr, &session->rtp.rem_addr.sin_addr);
00604         if (err < 0)
00605         {
00606                 ortp_warning ("Error in socket address:%s.", getSocketError());
00607                 return err;
00608         }
00609         session->rtp.rem_addr.sin_port = htons (rtp_port);
00610 
00611         memcpy (&session->rtcp.rem_addr, &session->rtp.rem_addr,
00612                 sizeof (struct sockaddr_in));
00613         session->rtcp.rem_addr.sin_port = htons (rtcp_port);
00614         session->rtcp.rem_addrlen=sizeof(session->rtcp.rem_addr);
00615 #endif
00616         if (can_connect(session)){
00617                 if (try_connect(session->rtp.socket,(struct sockaddr*)&session->rtp.rem_addr,session->rtp.rem_addrlen))
00618                         session->flags|=RTP_SOCKET_CONNECTED;
00619                 if (session->rtcp.socket>=0){
00620                         if (try_connect(session->rtcp.socket,(struct sockaddr*)&session->rtcp.rem_addr,session->rtcp.rem_addrlen))
00621                                 session->flags|=RTCP_SOCKET_CONNECTED;
00622                 }
00623         }else if (session->flags & RTP_SOCKET_CONNECTED){
00624                 /*must dissolve association done by connect().
00625                 See connect(2) manpage*/
00626                 struct sockaddr sa;
00627                 sa.sa_family=AF_UNSPEC;
00628                 if (connect(session->rtp.socket,&sa,sizeof(sa))<0){
00629                         ortp_error("Cannot dissolve connect() association for rtp socket: %s", getSocketError());
00630                 }
00631                 if (connect(session->rtcp.socket,&sa,sizeof(sa))<0){
00632                         ortp_error("Cannot dissolve connect() association for rtcp socket: %s", getSocketError());
00633                 }
00634                 session->flags&=~RTP_SOCKET_CONNECTED;
00635                 session->flags&=~RTCP_SOCKET_CONNECTED;
00636         }
00637         return 0;
00638 }
00639 
00640 void rtp_session_set_sockets(RtpSession *session, int rtpfd, int rtcpfd)
00641 {
00642         if (rtpfd>=0) set_non_blocking_socket(rtpfd);
00643         if (rtcpfd>=0) set_non_blocking_socket(rtcpfd);
00644         session->rtp.socket=rtpfd;
00645         session->rtcp.socket=rtcpfd;
00646         if (rtpfd>=0 || rtcpfd>=0 )
00647                 session->flags|=(RTP_SESSION_USING_EXT_SOCKETS|RTP_SOCKET_CONNECTED|RTCP_SOCKET_CONNECTED);
00648         else session->flags&=~(RTP_SESSION_USING_EXT_SOCKETS|RTP_SOCKET_CONNECTED|RTCP_SOCKET_CONNECTED);
00649 }
00650 
00651 void rtp_session_set_transports(RtpSession *session, struct _RtpTransport *rtptr, struct _RtpTransport *rtcptr)
00652 {
00653         session->rtp.tr = rtptr;
00654         session->rtcp.tr = rtcptr;
00655         if (rtptr)
00656                 rtptr->session=session;
00657         if (rtcptr)
00658                 rtcptr->session=session;
00659 
00660         if (rtptr || rtcptr )
00661                 session->flags|=(RTP_SESSION_USING_TRANSPORT);
00662         else session->flags&=~(RTP_SESSION_USING_TRANSPORT);
00663 }
00664 
00665 
00666 
00677 void rtp_session_flush_sockets(RtpSession *session){
00678         unsigned char trash[4096];
00679 #ifdef ORTP_INET6
00680         struct sockaddr_storage from;
00681 #else
00682         struct sockaddr from;
00683 #endif
00684         socklen_t fromlen=sizeof(from);
00685         if (rtp_session_using_transport(session, rtp))
00686           {
00687                 mblk_t *trashmp=esballoc(trash,sizeof(trash),0,NULL);
00688                 
00689             while (session->rtp.tr->t_recvfrom(session->rtp.tr,trashmp,0,(struct sockaddr *)&from,&fromlen)>0){};
00690 
00691             if (session->rtcp.tr)
00692               while (session->rtcp.tr->t_recvfrom(session->rtcp.tr,trashmp,0,(struct sockaddr *)&from,&fromlen)>0){};
00693                 freemsg(trashmp);
00694             return;
00695           }
00696 
00697         if (session->rtp.socket>=0){
00698                 while (recvfrom(session->rtp.socket,trash,sizeof(trash),0,(struct sockaddr *)&from,&fromlen)>0){};
00699         }
00700         if (session->rtcp.socket>=0){
00701                 while (recvfrom(session->rtcp.socket,trash,sizeof(trash),0,(struct sockaddr*)&from,&fromlen)>0){};
00702         }
00703 }
00704 
00705 
00706 #ifdef USE_SENDMSG 
00707 #define MAX_IOV 30
00708 static int rtp_sendmsg(int sock,mblk_t *m, struct sockaddr *rem_addr, int addr_len){
00709         int error;
00710         struct msghdr msg;
00711         struct iovec iov[MAX_IOV];
00712         int iovlen;
00713         for(iovlen=0; iovlen<MAX_IOV && m!=NULL; m=m->b_cont,iovlen++){
00714                 iov[iovlen].iov_base=m->b_rptr;
00715                 iov[iovlen].iov_len=m->b_wptr-m->b_rptr;
00716         }
00717         if (iovlen==MAX_IOV){
00718                 ortp_error("Too long msgb, didn't fit into iov, end discarded.");
00719         }
00720         msg.msg_name=(void*)rem_addr;
00721         msg.msg_namelen=addr_len;
00722         msg.msg_iov=&iov[0];
00723         msg.msg_iovlen=iovlen;
00724         msg.msg_control=NULL;
00725         msg.msg_controllen=0;
00726         msg.msg_flags=0;
00727         error=sendmsg(sock,&msg,0);
00728         return error;
00729 }
00730 #endif  
00731 
00732 #define IP_UDP_OVERHEAD (20+8)
00733 
00734 static void update_sent_bytes(RtpSession*s, int nbytes){
00735         if (s->rtp.sent_bytes==0){
00736                 gettimeofday(&s->rtp.send_bw_start,NULL);
00737         }
00738         s->rtp.sent_bytes+=nbytes+IP_UDP_OVERHEAD;
00739 }
00740 
00741 static void update_recv_bytes(RtpSession*s, int nbytes){
00742         if (s->rtp.recv_bytes==0){
00743                 gettimeofday(&s->rtp.recv_bw_start,NULL);
00744         }
00745         s->rtp.recv_bytes+=nbytes+IP_UDP_OVERHEAD;
00746 }
00747 
00748 int
00749 rtp_session_rtp_send (RtpSession * session, mblk_t * m)
00750 {
00751         int error;
00752         int i;
00753         rtp_header_t *hdr;
00754         struct sockaddr *destaddr=(struct sockaddr*)&session->rtp.rem_addr;
00755         socklen_t destlen=session->rtp.rem_addrlen;
00756         ortp_socket_t sockfd=session->rtp.socket;
00757 
00758         hdr = (rtp_header_t *) m->b_rptr;
00759         /* perform host to network conversions */
00760         hdr->ssrc = htonl (hdr->ssrc);
00761         hdr->timestamp = htonl (hdr->timestamp);
00762         hdr->seq_number = htons (hdr->seq_number);
00763         for (i = 0; i < hdr->cc; i++)
00764                 hdr->csrc[i] = htonl (hdr->csrc[i]);
00765 
00766         if (session->flags & RTP_SOCKET_CONNECTED) {
00767                 destaddr=NULL;
00768                 destlen=0;
00769         }
00770 
00771         if (rtp_session_using_transport(session, rtp)){
00772                 error = (session->rtp.tr->t_sendto) (session->rtp.tr,m,0,destaddr,destlen);
00773         }else{
00774 #ifdef USE_SENDMSG
00775                 error=rtp_sendmsg(sockfd,m,destaddr,destlen);
00776 #else
00777                 if (m->b_cont!=NULL)
00778                         msgpullup(m,-1);
00779                 error = sendto (sockfd, m->b_rptr, (int) (m->b_wptr - m->b_rptr),
00780                          0,destaddr,destlen);
00781 #endif
00782         }
00783         if (error < 0){
00784                 if (session->on_network_error.count>0){
00785                         rtp_signal_table_emit3(&session->on_network_error,(long)"Error sending RTP packet",INT_TO_POINTER(getSocketErrorCode()));
00786                 }else ortp_warning ("Error sending rtp packet: %s ; socket=%i", getSocketError(), sockfd);
00787                 session->rtp.send_errno=getSocketErrorCode();
00788         }else{
00789                 update_sent_bytes(session,error);
00790         }
00791         freemsg (m);
00792         return error;
00793 }
00794 
00795 int
00796 rtp_session_rtcp_send (RtpSession * session, mblk_t * m)
00797 {
00798         int error=0;
00799         ortp_socket_t sockfd=session->rtcp.socket;
00800         struct sockaddr *destaddr=(struct sockaddr*)&session->rtcp.rem_addr;
00801         socklen_t destlen=session->rtcp.rem_addrlen;
00802         bool_t using_connected_socket=(session->flags & RTCP_SOCKET_CONNECTED)!=0;
00803 
00804         if (using_connected_socket) {
00805                 destaddr=NULL;
00806                 destlen=0;
00807         }
00808 
00809         if (session->rtcp.enabled &&
00810                 ( (sockfd>=0 && (session->rtcp.rem_addrlen>0 ||using_connected_socket))
00811                         || rtp_session_using_transport(session, rtcp) ) ){
00812                 if (rtp_session_using_transport(session, rtcp)){
00813                         error = (session->rtcp.tr->t_sendto) (session->rtcp.tr, m, 0,
00814                         destaddr, destlen);
00815                 }
00816                 else{
00817 #ifdef USE_SENDMSG
00818                         error=rtp_sendmsg(sockfd,m,destaddr, destlen);
00819 #else
00820                         if (m->b_cont!=NULL){
00821                                 msgpullup(m,-1);
00822                         }
00823                         error = sendto (sockfd, m->b_rptr,
00824                         (int) (m->b_wptr - m->b_rptr), 0,
00825                         destaddr, destlen);
00826 #endif
00827                 }
00828                 if (error < 0){
00829                         char host[65];
00830                         if (session->on_network_error.count>0){
00831                                 rtp_signal_table_emit3(&session->on_network_error,(long)"Error sending RTCP packet",INT_TO_POINTER(getSocketErrorCode()));
00832                         }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)) );
00833                 }
00834         }else ortp_message("Not sending rtcp report: sockfd=%i, rem_addrlen=%i, connected=%i",sockfd,session->rtcp.rem_addrlen,using_connected_socket);
00835         freemsg (m);
00836         return error;
00837 }
00838 
00839 int
00840 rtp_session_rtp_recv (RtpSession * session, uint32_t user_ts)
00841 {
00842         int error;
00843         ortp_socket_t sockfd=session->rtp.socket;
00844 #ifdef ORTP_INET6
00845         struct sockaddr_storage remaddr;
00846 #else
00847         struct sockaddr remaddr;
00848 #endif
00849         socklen_t addrlen = sizeof (remaddr);
00850         mblk_t *mp;
00851         
00852         if ((sockfd<0) && !rtp_session_using_transport(session, rtp)) return -1;  /*session has no sockets for the moment*/
00853 
00854         while (1)
00855         {
00856                 int bufsz;
00857                 bool_t sock_connected=!!(session->flags & RTP_SOCKET_CONNECTED);
00858 
00859                 if (session->rtp.cached_mp==NULL)
00860                          session->rtp.cached_mp = allocb (session->recv_buf_size, 0);
00861                 mp=session->rtp.cached_mp;
00862                 bufsz=(int) (mp->b_datap->db_lim - mp->b_datap->db_base);
00863                 if (sock_connected){
00864                         error=recv(sockfd,mp->b_wptr,bufsz,0);
00865                 }else if (rtp_session_using_transport(session, rtp)) 
00866                         error = (session->rtp.tr->t_recvfrom)(session->rtp.tr, mp, 0,
00867                                   (struct sockaddr *) &remaddr,
00868                                   &addrlen);
00869                 else error = recvfrom(sockfd, mp->b_wptr,
00870                                   bufsz, 0,
00871                                   (struct sockaddr *) &remaddr,
00872                                   &addrlen);
00873                 if (error > 0){
00874                         if (session->symmetric_rtp && !sock_connected){
00875                                 /* store the sender rtp address to do symmetric RTP */
00876                                 memcpy(&session->rtp.rem_addr,&remaddr,addrlen);
00877                                 session->rtp.rem_addrlen=addrlen;
00878                                 if (session->use_connect){
00879                                         if (try_connect(sockfd,(struct sockaddr*)&remaddr,addrlen))
00880                                                 session->flags|=RTP_SOCKET_CONNECTED;
00881                                 }
00882                         }
00883                         /* then parse the message and put on queue */
00884                         mp->b_wptr+=error;
00885                         rtp_session_rtp_parse (session, mp, user_ts + session->rtp.hwrcv_diff_ts, (struct sockaddr*)&remaddr,addrlen);
00886                         session->rtp.cached_mp=NULL;
00887                         /*for bandwidth measurements:*/
00888                         update_recv_bytes(session,error);
00889                 }
00890                 else
00891                 {
00892                         int errnum=getSocketErrorCode();
00893 
00894                         if (error == 0)
00895                         {
00896                                 ortp_warning
00897                                         ("rtp_recv: strange... recv() returned zero.");
00898                         }
00899                         else if (!is_would_block_error(errnum))
00900                         {
00901                                 if (session->on_network_error.count>0){
00902                                         rtp_signal_table_emit3(&session->on_network_error,(long)"Error receiving RTP packet",INT_TO_POINTER(getSocketErrorCode()));
00903                                 }else ortp_warning("Error receiving RTP packet: %s.",getSocketError());
00904                         }
00905                         /* don't free the cached_mp, it will be reused next time */
00906                         return -1;      /* avoids an infinite loop ! */
00907                 }
00908         }
00909         return error;
00910 }
00911 
00912 void rtp_session_notify_inc_rtcp(RtpSession *session, mblk_t *m){
00913         if (session->eventqs!=NULL){
00914                 OrtpEvent *ev=ortp_event_new(ORTP_EVENT_RTCP_PACKET_RECEIVED);
00915                 OrtpEventData *d=ortp_event_get_data(ev);
00916                 d->packet=m;
00917                 rtp_session_dispatch_event(session,ev);
00918         }
00919         else
00920           freemsg(m);  /* avoid memory leak */
00921 }
00922 
00923 int
00924 rtp_session_rtcp_recv (RtpSession * session)
00925 {
00926         int error;
00927 #ifdef ORTP_INET6
00928         struct sockaddr_storage remaddr;
00929 #else
00930         struct sockaddr remaddr;
00931 #endif
00932         socklen_t addrlen=0;
00933         mblk_t *mp;
00934 
00935         if (session->rtcp.socket<0 && !rtp_session_using_transport(session, rtcp)) return -1;  /*session has no rtcp sockets for the moment*/
00936         
00937 
00938         while (1)
00939         {
00940                 bool_t sock_connected=!!(session->flags & RTCP_SOCKET_CONNECTED);
00941                 if (session->rtcp.cached_mp==NULL)
00942                          session->rtcp.cached_mp = allocb (RTCP_MAX_RECV_BUFSIZE, 0);
00943                 
00944                 mp=session->rtcp.cached_mp;
00945                 if (sock_connected){
00946                         error=recv(session->rtcp.socket,mp->b_wptr,RTCP_MAX_RECV_BUFSIZE,0);
00947                 }else {
00948                         addrlen=sizeof (remaddr);
00949 
00950                         if (rtp_session_using_transport(session, rtcp))
00951                           error=(session->rtcp.tr->t_recvfrom)(session->rtcp.tr, mp, 0,
00952                                   (struct sockaddr *) &remaddr,
00953                                   &addrlen);
00954                         else
00955                           error=recvfrom (session->rtcp.socket, mp->b_wptr,
00956                                   RTCP_MAX_RECV_BUFSIZE, 0,
00957                                   (struct sockaddr *) &remaddr,
00958                                   &addrlen);
00959                 }
00960                 if (error > 0)
00961                 {
00962                         mp->b_wptr += error;
00963                         /* post an event to notify the application*/
00964                         {
00965                                 rtp_session_notify_inc_rtcp(session,mp);
00966                         }
00967                         session->rtcp.cached_mp=NULL;
00968                         if (session->symmetric_rtp && !sock_connected){
00969                                 /* store the sender rtp address to do symmetric RTP */
00970                                 memcpy(&session->rtcp.rem_addr,&remaddr,addrlen);
00971                                 session->rtcp.rem_addrlen=addrlen;
00972                                 if (session->use_connect){
00973                                         if (try_connect(session->rtcp.socket,(struct sockaddr*)&remaddr,addrlen))
00974                                                 session->flags|=RTCP_SOCKET_CONNECTED;
00975                                 }
00976                         }
00977                 }
00978                 else
00979                 {
00980                         int errnum=getSocketErrorCode();
00981 
00982                         if (error == 0)
00983                         {
00984                                 ortp_warning
00985                                         ("rtcp_recv: strange... recv() returned zero.");
00986                         }
00987                         else if (!is_would_block_error(errnum))
00988                         {
00989                                 if (session->on_network_error.count>0){
00990                                         rtp_signal_table_emit3(&session->on_network_error,(long)"Error receiving RTCP packet",INT_TO_POINTER(errnum));
00991                                 }else ortp_warning("Error receiving RTCP packet: %s.",getSocketError());
00992                                 session->rtp.recv_errno=errnum;
00993                         }
00994                         /* don't free the cached_mp, it will be reused next time */
00995                         return -1;      /* avoids an infinite loop ! */
00996                 }
00997         }
00998         return error;
00999 }
01000 

Generated on Thu Feb 14 16:10:27 2008 for oRTP by  doxygen 1.5.4