/* * Copyright (c) 1995 The Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Network Research * Group at Lawrence Berkeley National Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static char rcsid[] = "@(#) $Header: /cs/research/mice/starship/src/local/CVS_repository/vic/rtp/session-ivs.cpp,v 1.1 1999/09/09 12:29:47 piers Exp $ (LBL)"; #endif #include #include "session-rtpv1.h" #include "source.h" #include "rtp.h" #include "ntp-time.h" /* * A class for backward compat with the old ivs variant * of RTPv1 (ivs-3.x and earlier). */ class IvsSessionManager : public RTPv1SessionManager { public: virtual void recv(CtrlHandler*); virtual void send_bye(); virtual void send_report(); protected: }; static class IvsSessionMatcher : public Matcher { public: IvsSessionMatcher() : Matcher("session") {} TclObject* match(const char* id) { if (strcmp(id, "video/ivs") == 0) return (new IvsSessionManager); else return (0); } } ivs_matcher; void IvsSessionManager::recv(CtrlHandler* ch) { /* * handle in incoming ivs session packet */ u_int32_t src; int cc = ch->recv(pktbuf_, 2 * RTP_MTU, src); if (cc <= 0) return; rtp1hdr* rh = (rtp1hdr*)pktbuf_; if (cc < sizeof(*rh)) { ++nrunt_; return; } if ((rh->rh_chan & 0xc0) != (1 << 6) || (rh->rh_flags & RTP1_OPTION_BIT) == 0) { ++badversion_; return; } u_int optflags; u_char* bp = (u_char*)(rh + 1); u_char* ep = bp + cc - sizeof(*rh);; u_int32_t addr = (u_int32_t)src; do { optflags = bp[0]; u_int optlen = bp[1] << 2; if (bp + optlen > ep || optlen == 0) { /* empty packet or bad optlen */ ++badoptions_; return; } switch (optflags & 0x7f) { Source* s; u_int len; char buf[256 + 32]; case 34: /* ivs's rtp v1 SDES opt */ len = bp[17] << 2; if (optlen < 20 || len > optlen - 16 || len < 4) { ++badoptions_; return; } len -= 2; s = SourceManager::instance().lookup(addr, addr, addr); if (s == 0) return; strncpy(buf, (char*)bp + 18, len); buf[len] = 0; if (bp[16] != 16) { len = strlen(buf); buf[len] = '@'; strcpy(buf + len + 1, intoa(addr)); s->sdes(RTCP_SDES_CNAME, buf); } else { if (s->sdes(RTCP_SDES_CNAME) == 0) s->sdes(RTCP_SDES_CNAME, intoa(addr)); s->sdes(RTCP_SDES_NAME, buf); } s->lts_ctrl(unixtime()); break; case 35: /* bye option */ if (optlen != 4) { ++badoptions_; return; } s = SourceManager::instance().consult(addr); if (s) s->lts_done(unixtime()); } bp += optlen; } while ((optflags & 0x80) == 0); } /* * Send an IVS report packet. */ void IvsSessionManager::send_report() { SourceManager& sm = SourceManager::instance(); Source& s = *sm.localsrc(); s.lts_ctrl(unixtime()); rtp1hdr* rh = (rtp1hdr*)pktbuf_; rh->rh_chan = 1 << 6; rh->rh_flags = RTP1_OPTION_BIT | RTP_PT_H261; rh->rh_seqno = 0; rh->rh_ts = 0; u_char* opt = (u_char*)(rh + 1); opt[0] = 127; /*APP option*/ opt[1] = 3; /*opt len*/ opt[2] = 0; opt[3] = 0; opt[4] = 'I'; opt[5] = 'V'; opt[6] = 'S'; opt[7] = ' '; opt[8] = 0x33; /*ivs version*/ opt[9] = (s.lts_data().tv_sec && int(s.lts_data().tv_sec - s.lts_ctrl().tv_sec) >= 0)? (1 << 6) : 0; opt[10] = 0; opt[11] = 0; opt += 12; opt[0] = 34 | 0x80; /*SDES option + Final*/ const char* name = s.sdes(RTCP_SDES_NAME); int len = strlen(name); int optlen = (len + (19 + 3)) >> 2; u_char* ep = opt + (optlen << 2); opt[1] = optlen; opt[2] = 0; /*id*/ opt[3] = 0; opt[4] = 2; /*port*/ opt[5] = 1; /*port len*/ Network* net = ch_.net(); opt[6] = ntohs(net->port()) >> 8; opt[7] = ntohs(net->port()); opt[8] = 1; /*addr*/ opt[9] = 2; /*addr len*/ opt[10] = 0; opt[11] = 1; /*addr type = ipv4*/ *(u_int*)&opt[12] = net->interface(); opt[16] = 16; /*class user text*/ opt[17] = optlen - 4; opt += 18; strcpy((char*)opt, name); opt += len; while (opt < ep) *opt++ = 0; len = ep - pktbuf_; net->send(pktbuf_, len); /* schedule a timer for the next report */ double rint = rtcp_inv_bw_ * 64.; if (rint < RTCP_MIN_RPT_TIME * 1000.) rint = RTCP_MIN_RPT_TIME * 1000.; rt_.msched(int(fmod(double(random()), rint) + rint * .5 + .5)); } void IvsSessionManager::send_bye() { rtp1hdr* rh = (rtp1hdr*)pktbuf_; rh->rh_chan = 1 << 6; rh->rh_flags = RTP1_OPTION_BIT | RTP_PT_H261; rh->rh_seqno = 0; rh->rh_ts = 0; u_char* opt = (u_char*)(rh + 1); opt[0] = 35 | 0x80; /*BYE option + Final*/ opt[1] = 1; opt[2] = 0; /*id*/ opt[3] = 0; ch_.send(pktbuf_, sizeof(*rh) + 4); }