message.cpp 4.89 KB
Newer Older
1 2 3
/*****************************************************************************
 * message.cpp : SAP Message class
 ****************************************************************************
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
4
 * Copyright (C) 1998-2006 the VideoLAN team
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
5
 * $Id$
6 7
 *
 * Authors: Damien Lucas <nitrox@videolan.org>
8
 *          Philippe Van Hecke <philippe.vanhecke@belnet.be>
9
 *          Derk-Jan Hartman <hartman at videolan dot org>
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
10
 *          Rémi Denis-Courmont <rem # videolan dot org>
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
30
#include <string.h>
31
#include <string>
32
#include <sstream>
33 34 35
#include <vector>
using namespace std;

36
#include "sapserver.h"
37 38 39
#include "program.h"
#include "message.h"

40 41
static const char mime_type[] = "application/sdp";

42 43 44
/*****************************************************************************
 * Constructors
 *****************************************************************************/
45
Message::Message(uint16_t v, const char* ip)
46 47 48
{
    version = v;

49 50 51 52 53
    u_long ip_server = inet_addr (ip); //TODO automaticaly get it ?
    msg_len = 4
            + 4 /* (IPv4 specific) */
          /*+ authentification length (N/A) */
            + sizeof (mime_type);
54

55 56 57
    msg = (uint8_t *)realloc (NULL, msg_len);
    if (msg == NULL)
        return; // TODO: throw an exception
58

59
    // Build the Message Header once initialized according to RFC 2974 (SAP)
60

61
    /* Byte 0 : Version number V1        = 001      (3 bits)
62 63 64 65 66
     *          Address type   IPv4/IPv6 = 0/1      (1 bit)
     *          Reserved                   0        (1 bit)
     *          Message Type   ann/del   = 0/1      (1 bit)
     *          Encryption     on/off    = 0/1      (1 bit)
     *          Compressed     on/off    = 0/1      (1 bit) */
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
    msg[0] = 0x20;
    //if ( ip_version == SAP_IPV6 ) msg[0] |= 0x10;
    //if ( type == SAP_DELETE ) msg[0] |= 0x04;
    //if ( encrypted ) msg[0] |= 0x02;
    //if ( compressed ) msg[0] |= 0x01;

    /* Byte 1 : Authentification length - Not supported */
    msg[1] = 0x00;

    /* Bytes 2-3 : Message Id Hash */
    msg[2] = version & 0xff;
    msg[3] = version >> 8;

    /* Bytes 4-7 (or 4-19) byte: Originating source */
    memcpy (msg + 4, &ip_server, 4);

    /* finally MIME type */
    memcpy (msg + 8, mime_type, sizeof (mime_type));
}

/*****************************************************************************
 * Destructor
 *****************************************************************************/
Message::~Message(void)
{
    if (msg != NULL)
        free (msg);
94 95
}

96 97

bool Message::AddProgram(Program *p)
98
{
99
    /* FIXME */
100 101
    /* RFC 2327 Compliance ? */
    string ipv = (p->GetAddress().find(':') == string::npos) ? "IP4" : "IP6";
102

103
    string sdp = "v=0\r\n";  // SDP version
104 105 106 107
    string ver="";
    stringstream ssin(ver);
    ssin << version;
    ver = ssin.str();
108 109 110 111 112 113 114 115 116 117 118 119
    sdp += "o=" + p->GetUser() + " " + ver + " 1 IN " + ipv + " "
              + p->GetMachine() + "\r\n";
    sdp += "s=" + p->GetName() + "\r\n";
    sdp += "u=" + p->GetSite() + "\r\n";

    sdp += "c=IN " + ipv + " " + p->GetAddress();
    if (ipv == "IP4")
        sdp += "/" + p->GetTTL(); /* only IPv4 multicast shall have a TTL */
    sdp += "\r\n";

    if (p->IsPermanent())
        sdp += "t=0 0\r\n";
120
    else
121 122
        return false;

123 124
    /* Session level attributes */
    sdp += "a=tool:" + (string)PACKAGE_STRING + "\r\n";
125

126 127
    if (p->HasPlGroup())
        sdp += "a=x-plgroup:" + p->GetPlGroup() + "\r\n";
128

129 130 131
    /* Media and media-level attributes */
    sdp += "a=type:broadcast\r\n";
    sdp += "a=charset:UTF-8\r\n";
132

133
    string m = "m=video " + p->GetPort() + " "
134
             + (p->IsRTP() ? "RTP/AVP 33" : "udp mpeg") +"\r\n";
135

136 137
    if (p->IsRTP())
        m += "a=rtpmap:33 MP2T/90000\r\n";
138

139
    sdp += m;
140

141
    puts (sdp.c_str ());
142

143 144 145
    if (msg_len + sdp.length () > 1024)
        //RFC 2974 Chap 6.
        return false;
146

147 148 149 150
    // updates full message
    uint8_t *newmsg = (uint8_t *)realloc (msg, msg_len + sdp.length ());
    if (newmsg == NULL)
        return false;
151

152 153 154 155
    // TODO: don't identically overwrite earlier programs
    memcpy (newmsg + msg_len, sdp.c_str(), sdp.length ());
    msg = newmsg;
    msg_len += sdp.length ();
156

157
    return true;
158
}