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 { 00055 terminate(); 00056 delete duplexA; 00057 delete duplexB; 00058 } 00059 00060 // Constructor. 00061 ccRTP_dupHello() : duplexA(NULL), duplexB(NULL) 00062 {} 00063 00064 // This method does almost everything. 00065 void run(void) 00066 { 00067 // redefined from Thread. 00068 00069 // Before using ccRTP you should learn something about other 00070 // CommonC++ classes. We need InetHostAddress... 00071 00072 // Construct loopback address 00073 InetHostAddress local_ip; 00074 local_ip = "127.0.0.1"; 00075 00076 // Is that correct? 00077 if( ! local_ip ) { 00078 // this is equivalent to `! local_ip.isInetAddress()' 00079 cerr << ": IP address is not correct!" << endl; 00080 exit(); 00081 } 00082 00083 cout << local_ip.getHostname() << 00084 " is going to talk to perself through " << 00085 local_ip << "..." << endl; 00086 00087 // ____Here comes the real RTP stuff____ 00088 00089 // Construct two RTPSocket. 22222 will be the base 00090 // port of A. 33334 will be the base port of B. 00091 const int A_BASE = 22222; 00092 const int B_BASE = 33334; 00093 00094 duplexA = new RTPDuplex(local_ip,A_BASE,B_BASE); 00095 00096 duplexB = new RTPDuplex(local_ip,B_BASE,A_BASE); 00097 00098 // Set up A's connection 00099 duplexA->setSchedulingTimeout(90000); 00100 duplexA->setExpireTimeout(2500000); 00101 if( duplexA->connect(local_ip,B_BASE) < 0 ) 00102 cerr << "Duplex A could not connect."; 00103 00104 // Set up B's connection 00105 duplexB->setSchedulingTimeout(160000); 00106 duplexB->setExpireTimeout(3500000); 00107 if( duplexB->connect(local_ip,A_BASE) < 0 ) 00108 cerr << "Duplex B could not connect."; 00109 00110 // Let's check the queues (you should read the documentation 00111 // so that you know what the queues are for). 00112 00113 if( duplexA->RTPDataQueue::isActive() ) 00114 cout << "The queue A is active." << endl; 00115 else 00116 cerr << "The queue A is not active." << endl; 00117 00118 if( duplexB->RTPDataQueue::isActive() ) 00119 cout << "The queue B is active." << endl; 00120 else 00121 cerr << "The queue B is not active." << endl; 00122 00123 00124 cout << "Transmitting..." << endl; 00125 00126 // This message will be sent on RTP packets, from A to 00127 // B and from B to A. 00128 unsigned char helloA[] = "Hello, brave gnu world from A!"; 00129 unsigned char helloB[] = "Hello, brave gnu world from B!"; 00130 00131 // This is not important 00132 time_t sending_time; 00133 time_t receiving_time; 00134 char tmstring[30]; 00135 00136 StaticPayloadFormat pf = sptMP2T; 00137 duplexA->setPayloadFormat(pf); 00138 duplexB->setPayloadFormat(pf); 00139 00140 // This is the main loop, where packets are sent and receipt. 00141 // A and B both will send and receive packets. 00142 for( int i = 0 ; true ; i++ ) { 00143 00144 // A and B do almost exactly the same things, 00145 // I have kept this here -out of a send/receive 00146 // method- in the interest of clarity. 00147 00148 // A: Send an RTP packet 00149 sending_time = time(NULL); 00150 duplexA->putData(2*(i)*90000,helloA, 00151 strlen((char *)helloA)); 00152 // Tell it 00153 strftime(tmstring,30,"%X",localtime(&sending_time)); 00154 cout << "A: sending message at " << tmstring << "..." 00155 << endl; 00156 00157 // A: Receive an RTP packet 00158 receiving_time = time(NULL); 00159 const AppDataUnit* aduA = 00160 duplexA->getData(duplexA->getFirstTimestamp()); 00161 if ( aduA ) { 00162 // Tell it 00163 strftime(tmstring,30,"%X",localtime(&receiving_time)); 00164 cout << "A:[receiving at " << tmstring << "]: " << 00165 aduA->getData() << endl; 00166 } 00167 // Wait for 0.1 seconds 00168 Thread::sleep(100); 00169 00170 // B: Send an RTP packet 00171 sending_time = time(NULL); 00172 duplexB->putData(2*(i)*90000,helloB, 00173 strlen((char *)helloB)); 00174 // Tell it 00175 strftime(tmstring,30,"%X",localtime(&sending_time)); 00176 cout << "B: sending message at " << tmstring << "..." 00177 << endl; 00178 00179 // B: Receive an RTP packet 00180 receiving_time = time(NULL); 00181 const AppDataUnit* aduB = 00182 duplexB->getData(duplexB->getFirstTimestamp()); 00183 if ( aduB ) { 00184 // Tell it 00185 strftime(tmstring,30,"%X",localtime(&receiving_time)); 00186 cout << "B:[receiving at " << tmstring << "]: " << 00187 aduB->getData() << endl; 00188 } 00189 00190 Thread::sleep(1900); 00191 } 00192 00193 } 00194 }; 00195 00196 int main(int argc, char *argv[]) 00197 { 00198 // Construct the main thread. It will not run yet. 00199 ccRTP_dupHello *hello = new ccRTP_dupHello; 00200 00201 cout << "This is rtpduphello, a very simple test program for ccRTP." 00202 << endl << "Strike [Enter] when you are fed up." << endl; 00203 00204 // Start execution of hello. 00205 hello->start(); 00206 00207 cin.get(); 00208 00209 cout << endl << "That's all" << endl; 00210 00211 delete hello; 00212 00213 exit(0); 00214 } 00215