# rtphello.cpp

A basic example of how to use RTPPacket

    // rtphello
    // A very simple program for testing and illustrating basic features of ccRTP.
    // Copyright (C) 2001,2002  Federico Montesino <fedemp@altern.org>
    //
    // 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-1307  USA

    // This is an introductory example file that illustrates basic usage
    // of ccRTP. You will also see a bit on how to use other classes from
    // CommonC++.

    // I am a typical hello world program. I consist of a sender thread,
    // that sends the salutation message on RTP packets; and a receiver
    // thread, that prints the messages. This is a program with an unsual
    // structure, the receiver just tries to process the first available
    // packet periodically, and both are in the same program. Thus, it
    // should not be seen as an example for typical applications but as a
    // test of some functions of ccRTP.

    #include <cstdio>
    #include <ctime>
    // In order to use ccRTP, the RTP stack of CommonC++, just include...
    #include <ccrtp/rtp.h>

    #ifdef  CCXX_NAMESPACES
    using namespace ost;
    using namespace std;
    #endif

    // base ports
    const int RECEIVER_BASE = 33634;
    const int TRANSMITTER_BASE = 32522;

    // For this example, this is irrelevant.
    //const int TIMESTAMP_RATE = 90000;

    class ccRTP_Hello_Rx: public Thread
    {

    private:
            // socket to receive packets
            RTPSession *socket;
            // loopback network address
            InetHostAddress local_ip;
            // identifier of this sender
            uint32 ssrc;

    public:
            ccRTP_Hello_Rx(){
                    // Before using ccRTP you should learn something about other
                    // CommonC++ classes. We need InetHostAddress...

                    // Construct loopback address
                    local_ip = "127.0.0.1";

                    // Is that correct?
                    if( ! local_ip ){
                            // this is equivalent to `! local_ip.isInetAddress()'
                            cerr << "Rx: IP address is not correct!" << endl;
                            exit();
                    }

                    // create socket for RTP connection and get a random
                    // SSRC identifier
                    socket = new RTPSession(local_ip,RECEIVER_BASE);
                    ssrc = socket->getLocalSSRC();
            }

            ~ccRTP_Hello_Rx(){
                    cout << endl << "Destroying receiver -ID: " << hex
                         << (int)ssrc;
                    terminate();
                    delete socket;
                    cout << "... " << "destroyed.";
            }

            // This method does almost everything.
            void run(void){

                    cout << "Hello, " << defaultApplication().
                            getSDESItem(SDESItemTypeCNAME)
                         << " ..." << endl;
                    // redefined from Thread.
                    // Set up connection
                    socket->setSchedulingTimeout(20000);
                    socket->setExpireTimeout(3000000);
                    //socket->UDPTransmit::setTypeOfService(SOCKET_IPTOS_LOWDELAY);
                    if( !socket->addDestination(local_ip,TRANSMITTER_BASE) )
                            cerr << "Rx (" << hex << (int)ssrc
                                 << "): could not connect to port."
                                 << TRANSMITTER_BASE;

                    cout << "Rx (" << hex << (int)ssrc
                         << "): " << local_ip.getHostname()
                         << " is waiting for salutes in port "
                         << RECEIVER_BASE << "..." << endl;

                    socket->setPayloadFormat(StaticPayloadFormat(sptMP2T));
                    socket->startRunning();
                    // Let's check the queues  (you should read the documentation
                    // so that you know what the queues are for).
                    cout << "Rx (" << hex << (int)ssrc
                         << "): The queue is "
                         << ( socket->isActive() ? "" : "in")
                         << "active." << endl;

                    // This is the main loop, where packets are received.
                    for( int i = 0 ; true ; i++ ){

                            // Wait for an RTP packet.
                            const AppDataUnit *adu = NULL;
                            while ( NULL == adu ) {
                                    Thread::sleep(10);
                                    adu = socket->getData(socket->getFirstTimestamp());
                            }

                            // Print content (likely a salute :))
                            // Note we are sure the data is an asciiz string.
                            time_t receiving_time = time(NULL);
                            char tmstring[30];
                            strftime(tmstring,30,"%X",localtime(&receiving_time));
                            cout << "Rx (" << hex << (int)ssrc
                                 << "): [receiving at " << tmstring << "]: "
                                 << adu->getData() << endl;
                            delete adu;
                    }
            }
    };

    class ccRTP_Hello_Tx: public Thread, public TimerPort
    {

    private:
            // socket to transmit
            RTPSession *socket;
            // loopback network address
            InetHostAddress local_ip;
            // identifier of this sender
            uint32 ssrc;

    public:
            ccRTP_Hello_Tx(){
                    // Before using ccRTP you should learn something about other
                    // CommonC++ classes. We need InetHostAddress...

                    // Construct loopback address
                    local_ip = "127.0.0.1";

                    // Is that correct?
                    if( ! local_ip ){
                    // this is equivalent to `! local_ip.isInetAddress()'
                            cerr << "Tx: IP address is not correct!" << endl;
                            exit();
                    }

                    socket = new RTPSession(local_ip,TRANSMITTER_BASE);
                    ssrc = socket->getLocalSSRC();
            }

            ~ccRTP_Hello_Tx(){
                    cout << endl << "Destroying transmitter -ID: " << hex
                         << (int)ssrc;
                    terminate();
                    delete socket;
                    cout << "... " << "destroyed.";
            }

            // This method does almost everything.
            void run(void){
                    // redefined from Thread.
                    cout << "Tx (" << hex << (int)ssrc << "): " <<
                            local_ip.getHostname()
                         << " is going to salute perself through "
                         << local_ip << "..." << endl;

                    // Set up connection
                    socket->setSchedulingTimeout(20000);
                    socket->setExpireTimeout(3000000);
                    if( !socket->addDestination(local_ip,RECEIVER_BASE) )
                            cerr << "Tx (" << hex << (int)ssrc
                                 << "): could not connect to port."
                                 << RECEIVER_BASE;

                    cout << "Tx (" << hex << (int)ssrc <<
                            "): Transmitting salutes to port "
                         << RECEIVER_BASE << "..." << endl;

                    uint32 timestamp = 0;
                    // This will be useful for periodic execution
                    TimerPort::setTimer(1000);

                    // This is the main loop, where packets are sent.
                    socket->setPayloadFormat(StaticPayloadFormat(sptMP2T));
                    socket->startRunning();
                    // Let's check the queues  (you should read the documentation
                    // so that you know what the queues are for).
                    cout << "Tx (" << hex << (int)ssrc << "): The queue is "
                         << ( socket->isActive()? "" : "in")
                         << "active." << endl;

                    for( int i = 0 ; true ;i++ ){

                            // send RTP packets, providing timestamp,
                            // payload type and payload.
                            // construct salute.
                            unsigned char salute[50];
                            snprintf((char *)salute,50,
                                     "Hello, brave gnu world (#%u)!",i);
                            time_t sending_time = time(NULL);
                            // get timestamp to send salute
                            if ( 0 == i ){
                                    timestamp = socket->getCurrentTimestamp();

                            } else {
                                    // increment for 1 second
                                    timestamp += socket->getCurrentRTPClockRate();
                            }

                            socket->putData(timestamp,salute,
                                            strlen((char *)salute)+1);
                            // print info
                            char tmstring[30];
                            strftime(tmstring,30,"%X",
                                     localtime(&sending_time));
                            cout << "Tx (" << hex << (int)ssrc
                                 << "): sending salute " << "no " << dec << i
                                 << ", at " << tmstring
                                 << "..." << endl;

                            // Let's wait for the next cycle
                            Thread::sleep(TimerPort::getTimer());
                            TimerPort::incTimer(1000);
                    }
            }
    };

    int main(int argc, char *argv[])
    {

            // Construct the two main threads. they will not run yet.
            ccRTP_Hello_Rx *receiver = new ccRTP_Hello_Rx;
            ccRTP_Hello_Tx *transmitter = new ccRTP_Hello_Tx;

            cout << "This is rtphello, a very simple test program for ccRTP." <<
                    endl << "Strike [Enter] when you are fed up with it." << endl;

            // Start execution of hello now.
            receiver->start();
            transmitter->start();

            cin.get();

            delete transmitter;
            delete receiver;

            cout << endl << "That's all." << endl;

            return 0;
    }