00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include <cc++/socketport.h>
00035
00036 #include <iostream>
00037
00038
00039
00040
00041
00042
00043
00044 #include <list>
00045
00046 #ifdef CCXX_NAMESPACES
00047 using namespace std;
00048 using namespace ost;
00049 #endif
00050
00051 class ts_list_item;
00052 typedef list<ts_list_item *> ts_list;
00053
00054
00055
00056
00057 class ts_list_head {
00058 public:
00059
00060
00061
00062
00063
00064 Mutex linkmutex;
00065
00066 ts_list list_o_items;
00067
00068
00069 ts_list_head()
00070 : linkmutex(), list_o_items()
00071 {
00072 }
00073
00074
00075 void RemoveListItem( ts_list_item * li );
00076 void InsertListItem( ts_list_item * li );
00077
00078
00079
00080 virtual void ListDepleted()
00081 {
00082 }
00083
00084 virtual ~ts_list_head()
00085 {
00086 }
00087 };
00088
00089
00090
00091
00092 class ts_list_item {
00093 public:
00094 ts_list::iterator linkpoint;
00095 ts_list_head * listhead;
00096
00097 virtual ~ts_list_item()
00098 {
00099 listhead->RemoveListItem( this );
00100 }
00101
00102 ts_list_item( ts_list_head * head )
00103 {
00104 listhead = head;
00105 head->InsertListItem( this );
00106 }
00107 };
00108
00109 void ts_list_head::RemoveListItem( ts_list_item * li )
00110 {
00111 bool is_empty;
00112 linkmutex.enterMutex();
00113 list_o_items.erase( li->linkpoint );
00114 is_empty = list_o_items.empty();
00115 linkmutex.leaveMutex();
00116
00117
00118
00119 if ( is_empty ) {
00120 ListDepleted();
00121 }
00122 }
00123
00124 void ts_list_head::InsertListItem( ts_list_item * li )
00125 {
00126 linkmutex.enterMutex();
00127 list_o_items.push_front( li );
00128 li->linkpoint = list_o_items.begin();
00129 linkmutex.leaveMutex();
00130 }
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 class ChatterSession :
00144 public virtual SocketPort,
00145 public virtual ts_list_item
00146 {
00147 public:
00148
00149 enum { size_o_buf = 2048 };
00150
00151
00152
00153
00154 virtual ~ChatterSession()
00155 {
00156 cerr << "ChatterSession deleted !\n";
00157 }
00158
00159
00160
00161 ChatterSession(
00162 TCPSocket & server,
00163 SocketService * svc,
00164 ts_list_head * head
00165 ) :
00166 SocketPort( NULL, server ),
00167 ts_list_item( head )
00168 {
00169 cerr << "ChatterSession Created\n";
00170
00171 tpport_t port;
00172 InetHostAddress ia = getPeer( & port );
00173
00174 cerr << "connecting from " << ia.getHostname() <<
00175 ":" << port << endl;
00176
00177
00178 setCompletion( false );
00179
00180
00181 setTimer( 100000 );
00182 attach(svc);
00183 }
00184
00185
00186
00187
00188
00189
00190 virtual void expired()
00191 {
00192
00193 cerr << "ChatterSession Expired\n";
00194 delete this;
00195 }
00196
00197
00198
00199
00200
00201
00202 virtual void pending()
00203 {
00204
00205
00206 cerr << "Pending called\n";
00207
00208
00209 setTimer( 100000 );
00210 try {
00211 int len;
00212 unsigned int total = 0;
00213 char buf[ size_o_buf ];
00214
00215 while ( (len = receive(buf, sizeof(buf) )) > 0 ) {
00216 total += len;
00217 cerr << "Read '";
00218 cerr.write( buf, len );
00219 cerr << "'\n";
00220
00221
00222
00223
00224
00225
00226
00227
00228 bool sent = false;
00229 listhead->linkmutex.enterMutex();
00230 for (
00231 ts_list::iterator iter = listhead->list_o_items.begin();
00232 iter != listhead->list_o_items.end();
00233 iter ++
00234 ) {
00235 ChatterSession * sess =
00236 dynamic_cast< ChatterSession * >( * iter );
00237 if ( sess != this ) {
00238 sess->send( buf, len );
00239 sent = true;
00240 }
00241 }
00242 listhead->linkmutex.leaveMutex();
00243
00244 if ( ! sent ) {
00245 send(
00246 ( void * ) "No one else listening\n",
00247 sizeof( "No one else listening\n" ) - 1
00248 );
00249
00250 send( buf, len );
00251 }
00252 }
00253 if (total == 0)
00254 {
00255 cerr << "Broken connection!\n" << endl;
00256 delete this;
00257 }
00258 }
00259 catch ( ... )
00260 {
00261
00262 cerr << "Socket port write sent an exception !\n";
00263 }
00264
00265 }
00266
00267 virtual void disconnect()
00268 {
00269
00270
00271 cerr << "ChatterSession disconnected!\n";
00272
00273 delete this;
00274 }
00275
00276 };
00277
00278 class ChatterThread;
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 class CCExec : public virtual ts_list_head {
00290 public:
00291
00292 SocketService * service;
00293 ChatterThread * my_Chatter;
00294 Semaphore mainsem[1];
00295
00296 CCExec():my_Chatter(NULL)
00297 {
00298 service = new SocketService( 0 );
00299 }
00300
00301 virtual void ListDepleted();
00302
00303
00304 virtual ~CCExec();
00305 int RunApp( char * hn = "localhost" );
00306
00307 };
00308
00309
00310
00311
00312
00313
00314
00315 class ChatterThread : public virtual TCPSocket, public virtual Thread {
00316 public:
00317
00318 CCExec * exec;
00319
00320 void run ()
00321 {
00322 while ( 1 ) {
00323 try {
00324
00325
00326
00327 new ChatterSession(
00328 * ( TCPSocket * ) this,
00329 exec->service,
00330 exec
00331 );
00332 }
00333 catch ( ... )
00334 {
00335
00336 cerr << "ChatterSession create failed\n";
00337 exit();
00338 }
00339 }
00340 }
00341
00342 ChatterThread(
00343 InetHostAddress & machine,
00344 int port,
00345 CCExec * inexec
00346
00347 ) : TCPSocket( machine, port ),
00348 Thread(),
00349 exec( inexec )
00350 {
00351 start();
00352 }
00353
00354
00355 };
00356
00357
00358
00359
00360
00361 CCExec::~CCExec()
00362 {
00363
00364
00365 if ( my_Chatter ) delete my_Chatter;
00366
00367
00368 delete service;
00369 }
00370
00371
00372
00373
00374
00375 int CCExec::RunApp( char * hn )
00376 {
00377
00378
00379 InetHostAddress machine( hn );
00380
00381 if ( machine.isInetAddress() == false ) {
00382 cerr << "machine is not address" << endl;
00383 }
00384
00385 cerr << "machine is " << machine.getHostname() << endl;
00386
00387
00388
00389 try {
00390 my_Chatter = new ChatterThread(
00391 machine,
00392 3999,
00393 this
00394 );
00395 }
00396 catch ( ... )
00397 {
00398 cerr << "Failed to bind\n";
00399 return false;
00400 }
00401
00402 return true;
00403 }
00404
00405
00406 void CCExec::ListDepleted()
00407 {
00408 mainsem->post();
00409 }
00410
00411
00412 int main( int argc, char ** argv )
00413 {
00414 CCExec * server;
00415
00416 server = new CCExec();
00417
00418
00419
00420 if ( argc > 1 ) {
00421 server->RunApp( argv[ 1 ] );
00422 } else {
00423 server->RunApp();
00424 }
00425
00426 server->mainsem->wait();
00427
00428 delete server;
00429
00430 return 0;
00431 }