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 
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                 /* the session has not its socket bound, do it */
00527                 ortp_message ("Setting random local addresses.");
00528 #ifdef ORTP_INET6
00529                 /* bind to an address type that matches the destination address */
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                 /* set a destination address that has the same type as the local address */
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                 /* set a destination address that has the same type as the local address */
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                 /*must dissolve association done by connect().
00606                 See connect(2) manpage*/
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         /* perform host to network conversions */
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;  /*session has no sockets for the moment*/
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                                 /* store the sender rtp address to do symmetric RTP */
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                         /* then parse the message and put on queue */
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                         /*for bandwidth measurements:*/
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                         /* don't free the cached_mp, it will be reused next time */
00879                         return -1;      /* avoids an infinite loop ! */
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);  /* avoid memory leak */
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;  /*session has no rtcp sockets for the moment*/
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                         /* post an event to notify the application*/
00938                         {
00939                                 rtp_session_notify_inc_rtcp(session,mp);
00940                         }
00941                         session->rtcp.cached_mp=NULL;
00942                         if (session->symmetric_rtp && !sock_connected){
00943                                 /* store the sender rtp address to do symmetric RTP */
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                         /* don't free the cached_mp, it will be reused next time */
00968                         return -1;      /* avoids an infinite loop ! */
00969                 }
00970         }
00971         return error;
00972 }
00973 

Generated on Wed Aug 29 01:18:36 2007 for oRTP by  doxygen 1.5.2