rtcp_recv.c

Go to the documentation of this file.
00001 /* * 
00002  * This file is part of libnemesi
00003  *
00004  * Copyright (C) 2007 by LScube team <team@streaming.polito.it>
00005  * See AUTHORS for more details
00006  * 
00007  * libnemesi is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * libnemesi is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with libnemesi; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  *  
00021  * */
00022 
00028 #include <errno.h>
00029 #include "rtcp.h"
00030 
00037 static int rtcp_hdr_val_chk(rtcp_pkt * pkt, int len)
00038 {
00039     rtcp_pkt *end;
00040 
00041     if (len < (int) sizeof(rtcp_common_t)) {
00042         nms_printf(NMSML_ERR, "RTCP packet too small!!! (%d)\n", len);
00043         return 1;
00044     }
00045 
00046     if (len / 4 > (ntohs((pkt->common).len) + 1)) {
00047         /* This is a fu**ing compound pkt */
00048         nms_printf(NMSML_DBG2,
00049                "RTCP Compound packet arrived (total len=%d)\n",
00050                len);
00051         if ((*(uint16_t *) pkt & RTCP_VALID_MASK) != RTCP_VALID_VALUE) {
00052             nms_printf(NMSML_WARN,
00053                    "RTCP Header not valid: first pkt of Compound is not a SR (or RR)!\n"
00054                    BLANK_LINE);
00055             return 1;
00056         }
00057         end = (rtcp_pkt *) ((uint32_t *) pkt + len / 4);
00058         do
00059             pkt =
00060                 (rtcp_pkt *) ((uint32_t *) pkt +
00061                       ntohs((pkt->common).len) + 1);
00062         while ((pkt < end) && ((pkt->common).ver == 2));
00063 
00064         if (pkt != end) {
00065             nms_printf(NMSML_WARN,
00066                    "RTCP Header not valid: mismatching lenght (%d)!\n"
00067                    BLANK_LINE, len);
00068             return 1;
00069         }
00070     } else {
00071         nms_printf(NMSML_DBG2, "RTCP packet arrived (total len=%d)\n",
00072                len);
00073         if ((pkt->common).ver != RTP_VERSION) {
00074             nms_printf(NMSML_WARN,
00075                    "RTCP Header not valid: mismatching RTP version number!\n"
00076                    BLANK_LINE);
00077             return 1;
00078         }
00079         if (!(((pkt->common).pt >= 200) && ((pkt->common).pt <= 204))) {
00080             nms_printf(NMSML_WARN,
00081                    "RTCP Header not valid: mismatching payload type!\n"
00082                    BLANK_LINE);
00083             return 1;
00084         }
00085         if (((pkt->common).pad)
00086             && (*(((uint8_t *) pkt) + len - 1) > (pkt->common).len * 4)) {
00087             nms_printf(NMSML_WARN,
00088                    "RTCP Header not valid: mismatching lenght!\n"
00089                    BLANK_LINE);
00090             return 1;
00091         }
00092     }
00093 
00094     return 0;
00095 }
00096 
00102 int rtcp_recv(rtp_session * rtp_sess)
00103 {
00104     uint8_t buffer[1024];
00105     rtp_ssrc *stm_src;
00106 
00107     struct sockaddr_storage serveraddr;
00108     nms_sockaddr server =
00109         { (struct sockaddr *) &serveraddr, sizeof(serveraddr) };
00110 
00111     rtcp_pkt *pkt;
00112     int ret, n;
00113 
00114     memset(buffer, 0, 1024);
00115 
00116     if ((n =
00117          recvfrom(rtp_sess->transport.RTCP.sock.fd, buffer, 1024, 0, server.addr,
00118               &server.addr_len)) == -1) {
00119         switch (errno) {
00120         case EBADF:
00121             nms_printf(NMSML_ERR,
00122                    "RTCP recvfrom: invalid descriptor\n");
00123             break;
00124 #ifndef WIN32
00125         case ENOTSOCK:
00126             nms_printf(NMSML_ERR, "RTCP recvfrom: not a socket\n");
00127             break;
00128 #endif
00129         case EINTR:
00130             nms_printf(NMSML_ERR,
00131                    "RTCP recvfrom: The receive was interrupted by delivery of a signal\n");
00132             break;
00133         case EFAULT:
00134             nms_printf(NMSML_ERR,
00135                    "RTCP recvfrom: The buffer points outside userspace\n");
00136             break;
00137         case EINVAL:
00138             nms_printf(NMSML_ERR,
00139                    "RTCP recvfrom: Invalid argument passed.\n");
00140             break;
00141         default:
00142             nms_printf(NMSML_ERR, "in RTCP recvfrom\n");
00143             break;
00144         }
00145         return 1;
00146     }
00147 
00148     pkt = (rtcp_pkt *) buffer;
00149 
00150     if (rtcp_hdr_val_chk(pkt, n)) {
00151         nms_printf(NMSML_WARN,
00152                "RTCP Header Validity Check failed!" BLANK_LINE);
00153         return 1;
00154     }
00155 
00156     switch (rtp_ssrc_check
00157         (rtp_sess, ntohl((pkt->r).sr.ssrc), &stm_src, &server, RTCP)) {
00158     case SSRC_NEW:
00159         if (pkt->common.pt == RTCP_SR)
00160             rtp_sess->sess_stats.senders++;
00161         rtp_sess->sess_stats.members++;
00162     case SSRC_RTCPNEW:
00163         break;
00164     case -1:
00165         return 1;
00166         break;
00167     default:
00168         break;
00169     }
00170 
00171     if ((ret = rtcp_parse_pkt(stm_src, pkt, n)) != 0)
00172         return ret;
00173     else
00174         rtp_sess->sess_stats.avg_rtcp_size =
00175             n / 16. + rtp_sess->sess_stats.avg_rtcp_size * 15. / 16.;
00176 
00177     return 0;
00178 }
00179 
00187 int rtcp_parse_pkt(rtp_ssrc * stm_src, rtcp_pkt * pkt, int len)
00188 {
00189     rtcp_pkt *end;
00190     end = (rtcp_pkt *) ((uint32_t *) pkt + len / 4);
00191 
00192     while (pkt < end) {
00193         switch ((pkt->common).pt) {
00194         case RTCP_SR:
00195             rtcp_parse_sr(stm_src, pkt);
00196             break;
00197         case RTCP_SDES:
00198             if (rtcp_parse_sdes(stm_src, pkt))
00199                 return -1;
00200             break;
00201         case RTCP_RR:
00202             rtcp_parse_rr(pkt);
00203             break;
00204         case RTCP_BYE:
00205             rtcp_parse_bye(stm_src, pkt);
00206             break;
00207         case RTCP_APP:
00208             rtcp_parse_app(pkt);
00209             break;
00210         default:
00211             nms_printf(NMSML_WARN, "Received unknown RTCP pkt\n");
00212             return 1;
00213         }
00214         pkt =
00215             (rtcp_pkt *) ((uint32_t *) pkt + ntohs((pkt->common).len) +
00216                   1);
00217     }
00218     return 0;
00219 }

Generated on Tue Feb 3 03:10:02 2009 for libnemesi by  doxygen 1.5.4