00001 // rtpduphello. 00002 // A very simple program for testing and illustrating basic features of ccRTP. 00003 // Copyright (C) 2001,2002 Federico Montesino <fedemp@altern.org> 00004 // 00005 // This program is free software; you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation; either version 2 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // This program 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 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 00020 // This is an introductory example file that illustrates basic usage 00021 // of ccRTP. You will also see a bit on how to use CommonC++ threads. 00022 00023 // It is a typical hello world program. It consists of tow duplex 00024 // connections that talk each other through RTP packets. They do not 00025 // say more than a typical salutation message. They both send and 00026 // receive messages, and print the messages they receive. 00027 00028 00029 #include <cstdio> 00030 #include <cstdlib> 00031 // In order to use ccRTP, the RTP stack of CommonC++, you only need to 00032 // include ... 00033 #include <ccrtp/ext.h> 00034 00035 #ifdef CCXX_NAMESPACES 00036 using namespace ost; 00037 using namespace std; 00038 #endif 00039 00044 class ccRTP_dupHello: public Thread 00045 { 00046 private: 00047 // There will be two duplex connections. They both will send 00048 // and receive packets. 00049 RTPDuplex *duplexA, *duplexB; 00050 00051 public: 00052 // Destructor. 00053 ~ccRTP_dupHello(){ 00054 terminate(); 00055 delete duplexA; 00056 delete duplexB; 00057 } 00058 00059 // Constructor. 00060 ccRTP_dupHello() : duplexA(NULL), duplexB(NULL) 00061 { } 00062 00063 // This method does almost everything. 00064 void run(void){ 00065 // redefined from Thread. 00066 00067 // Before using ccRTP you should learn something about other 00068 // CommonC++ classes. We need InetHostAddress... 00069 00070 // Construct loopback address 00071 InetHostAddress local_ip; 00072 local_ip = "127.0.0.1"; 00073 00074 // Is that correct? 00075 if( ! local_ip ){ 00076 // this is equivalent to `! local_ip.isInetAddress()' 00077 cerr << ": IP address is not correct!" << endl; 00078 exit(); 00079 } 00080 00081 cout << local_ip.getHostname() << 00082 " is going to talk to perself through " << 00083 local_ip << "..." << endl; 00084 00085 // ____Here comes the real RTP stuff____ 00086 00087 // Construct two RTPSocket. 22222 will be the base 00088 // port of A. 33334 will be the base port of B. 00089 const int A_BASE = 22222; 00090 const int B_BASE = 33334; 00091 00092 duplexA = new RTPDuplex(local_ip,A_BASE,B_BASE); 00093 00094 duplexB = new RTPDuplex(local_ip,B_BASE,A_BASE); 00095 00096 // Set up A's connection 00097 duplexA->setSchedulingTimeout(90000); 00098 duplexA->setExpireTimeout(2500000); 00099 if( duplexA->connect(local_ip,B_BASE) < 0 ) 00100 cerr << "Duplex A could not connect."; 00101 00102 // Set up B's connection 00103 duplexB->setSchedulingTimeout(160000); 00104 duplexB->setExpireTimeout(3500000); 00105 if( duplexB->connect(local_ip,A_BASE) < 0 ) 00106 cerr << "Duplex B could not connect."; 00107 00108 // Let's check the queues (you should read the documentation 00109 // so that you know what the queues are for). 00110 00111 if( duplexA->RTPDataQueue::isActive() ) 00112 cout << "The queue A is active." << endl; 00113 else 00114 cerr << "The queue A is not active." << endl; 00115 00116 if( duplexB->RTPDataQueue::isActive() ) 00117 cout << "The queue B is active." << endl; 00118 else 00119 cerr << "The queue B is not active." << endl; 00120 00121 00122 cout << "Transmitting..." << endl; 00123 00124 // This message will be sent on RTP packets, from A to 00125 // B and from B to A. 00126 unsigned char helloA[] = "Hello, brave gnu world from A!"; 00127 unsigned char helloB[] = "Hello, brave gnu world from B!"; 00128 00129 // This is not important 00130 time_t sending_time; 00131 time_t receiving_time; 00132 char tmstring[30]; 00133 00134 StaticPayloadFormat pf = sptMP2T; 00135 duplexA->setPayloadFormat(pf); 00136 duplexB->setPayloadFormat(pf); 00137 00138 // This is the main loop, where packets are sent and receipt. 00139 // A and B both will send and receive packets. 00140 for( int i = 0 ; true ; i++ ){ 00141 00142 // A and B do almost exactly the same things, 00143 // I have kept this here -out of a send/receive 00144 // method- in the interest of clarity. 00145 00146 // A: Send an RTP packet 00147 sending_time = time(NULL); 00148 duplexA->putData(2*(i)*90000,helloA, 00149 strlen((char *)helloA)); 00150 // Tell it 00151 strftime(tmstring,30,"%X",localtime(&sending_time)); 00152 cout << "A: sending message at " << tmstring << "..." 00153 << endl; 00154 00155 // A: Receive an RTP packet 00156 receiving_time = time(NULL); 00157 const AppDataUnit* aduA = 00158 duplexA->getData(duplexA->getFirstTimestamp()); 00159 if ( aduA ) { 00160 // Tell it 00161 strftime(tmstring,30,"%X",localtime(&receiving_time)); 00162 cout << "A:[receiving at " << tmstring << "]: " << 00163 aduA->getData() << endl; 00164 } 00165 // Wait for 0.1 seconds 00166 Thread::sleep(100); 00167 00168 // B: Send an RTP packet 00169 sending_time = time(NULL); 00170 duplexB->putData(2*(i)*90000,helloB, 00171 strlen((char *)helloB)); 00172 // Tell it 00173 strftime(tmstring,30,"%X",localtime(&sending_time)); 00174 cout << "B: sending message at " << tmstring << "..." 00175 << endl; 00176 00177 // B: Receive an RTP packet 00178 receiving_time = time(NULL); 00179 const AppDataUnit* aduB = 00180 duplexB->getData(duplexB->getFirstTimestamp()); 00181 if ( aduB ) { 00182 // Tell it 00183 strftime(tmstring,30,"%X",localtime(&receiving_time)); 00184 cout << "B:[receiving at " << tmstring << "]: " << 00185 aduB->getData() << endl; 00186 } 00187 00188 Thread::sleep(1900); 00189 } 00190 00191 } 00192 }; 00193 00194 int main(int argc, char *argv[]) 00195 { 00196 // Construct the main thread. It will not run yet. 00197 ccRTP_dupHello *hello = new ccRTP_dupHello; 00198 00199 cout << "This is rtpduphello, a very simple test program for ccRTP." 00200 << endl << "Strike [Enter] when you are fed up." << endl; 00201 00202 // Start execution of hello. 00203 hello->start(); 00204 00205 cin.get(); 00206 00207 cout << endl << "That's all" << endl; 00208 00209 delete hello; 00210 00211 exit(0); 00212 } 00213