annotate oscpack/ip/win32/UdpSocket.cpp @ 101:52e44ee1c791 tip master

enabled all scores in autostart script
author Rob Canning <rc@kiben.net>
date Tue, 21 Apr 2015 16:20:57 +0100
parents 0ae87af84e2f
children
rev   line source
rob@76 1 /*
rob@76 2 oscpack -- Open Sound Control (OSC) packet manipulation library
rob@76 3 http://www.rossbencina.com/code/oscpack
rob@76 4
rob@76 5 Copyright (c) 2004-2013 Ross Bencina <rossb@audiomulch.com>
rob@76 6
rob@76 7 Permission is hereby granted, free of charge, to any person obtaining
rob@76 8 a copy of this software and associated documentation files
rob@76 9 (the "Software"), to deal in the Software without restriction,
rob@76 10 including without limitation the rights to use, copy, modify, merge,
rob@76 11 publish, distribute, sublicense, and/or sell copies of the Software,
rob@76 12 and to permit persons to whom the Software is furnished to do so,
rob@76 13 subject to the following conditions:
rob@76 14
rob@76 15 The above copyright notice and this permission notice shall be
rob@76 16 included in all copies or substantial portions of the Software.
rob@76 17
rob@76 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
rob@76 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
rob@76 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
rob@76 21 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
rob@76 22 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
rob@76 23 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
rob@76 24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
rob@76 25 */
rob@76 26
rob@76 27 /*
rob@76 28 The text above constitutes the entire oscpack license; however,
rob@76 29 the oscpack developer(s) also make the following non-binding requests:
rob@76 30
rob@76 31 Any person wishing to distribute modifications to the Software is
rob@76 32 requested to send the modifications to the original developer so that
rob@76 33 they can be incorporated into the canonical version. It is also
rob@76 34 requested that these non-binding requests be included whenever the
rob@76 35 above license is reproduced.
rob@76 36 */
rob@76 37
rob@76 38 #include <winsock2.h> // this must come first to prevent errors with MSVC7
rob@76 39 #include <windows.h>
rob@76 40 #include <mmsystem.h> // for timeGetTime()
rob@76 41
rob@76 42 #ifndef WINCE
rob@76 43 #include <signal.h>
rob@76 44 #endif
rob@76 45
rob@76 46 #include <algorithm>
rob@76 47 #include <cassert>
rob@76 48 #include <cstring> // for memset
rob@76 49 #include <stdexcept>
rob@76 50 #include <vector>
rob@76 51
rob@76 52 #include "ip/UdpSocket.h" // usually I'd include the module header first
rob@76 53 // but this is causing conflicts with BCB4 due to
rob@76 54 // std::size_t usage.
rob@76 55
rob@76 56 #include "ip/NetworkingUtils.h"
rob@76 57 #include "ip/PacketListener.h"
rob@76 58 #include "ip/TimerListener.h"
rob@76 59
rob@76 60
rob@76 61 typedef int socklen_t;
rob@76 62
rob@76 63
rob@76 64 static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
rob@76 65 {
rob@76 66 std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
rob@76 67 sockAddr.sin_family = AF_INET;
rob@76 68
rob@76 69 sockAddr.sin_addr.s_addr =
rob@76 70 (endpoint.address == IpEndpointName::ANY_ADDRESS)
rob@76 71 ? INADDR_ANY
rob@76 72 : htonl( endpoint.address );
rob@76 73
rob@76 74 sockAddr.sin_port =
rob@76 75 (endpoint.port == IpEndpointName::ANY_PORT)
rob@76 76 ? (short)0
rob@76 77 : htons( (short)endpoint.port );
rob@76 78 }
rob@76 79
rob@76 80
rob@76 81 static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
rob@76 82 {
rob@76 83 return IpEndpointName(
rob@76 84 (sockAddr.sin_addr.s_addr == INADDR_ANY)
rob@76 85 ? IpEndpointName::ANY_ADDRESS
rob@76 86 : ntohl( sockAddr.sin_addr.s_addr ),
rob@76 87 (sockAddr.sin_port == 0)
rob@76 88 ? IpEndpointName::ANY_PORT
rob@76 89 : ntohs( sockAddr.sin_port )
rob@76 90 );
rob@76 91 }
rob@76 92
rob@76 93
rob@76 94 class UdpSocket::Implementation{
rob@76 95 NetworkInitializer networkInitializer_;
rob@76 96
rob@76 97 bool isBound_;
rob@76 98 bool isConnected_;
rob@76 99
rob@76 100 SOCKET socket_;
rob@76 101 struct sockaddr_in connectedAddr_;
rob@76 102 struct sockaddr_in sendToAddr_;
rob@76 103
rob@76 104 public:
rob@76 105
rob@76 106 Implementation()
rob@76 107 : isBound_( false )
rob@76 108 , isConnected_( false )
rob@76 109 , socket_( INVALID_SOCKET )
rob@76 110 {
rob@76 111 if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == INVALID_SOCKET ){
rob@76 112 throw std::runtime_error("unable to create udp socket\n");
rob@76 113 }
rob@76 114
rob@76 115 std::memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
rob@76 116 sendToAddr_.sin_family = AF_INET;
rob@76 117 }
rob@76 118
rob@76 119 ~Implementation()
rob@76 120 {
rob@76 121 if (socket_ != INVALID_SOCKET) closesocket(socket_);
rob@76 122 }
rob@76 123
rob@76 124 void SetEnableBroadcast( bool enableBroadcast )
rob@76 125 {
rob@76 126 char broadcast = (char)((enableBroadcast) ? 1 : 0); // char on win32
rob@76 127 setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
rob@76 128 }
rob@76 129
rob@76 130 void SetAllowReuse( bool allowReuse )
rob@76 131 {
rob@76 132 // Note: SO_REUSEADDR is non-deterministic for listening sockets on Win32. See MSDN article:
rob@76 133 // "Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE"
rob@76 134 // http://msdn.microsoft.com/en-us/library/ms740621%28VS.85%29.aspx
rob@76 135
rob@76 136 char reuseAddr = (char)((allowReuse) ? 1 : 0); // char on win32
rob@76 137 setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr));
rob@76 138 }
rob@76 139
rob@76 140 IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
rob@76 141 {
rob@76 142 assert( isBound_ );
rob@76 143
rob@76 144 // first connect the socket to the remote server
rob@76 145
rob@76 146 struct sockaddr_in connectSockAddr;
rob@76 147 SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
rob@76 148
rob@76 149 if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
rob@76 150 throw std::runtime_error("unable to connect udp socket\n");
rob@76 151 }
rob@76 152
rob@76 153 // get the address
rob@76 154
rob@76 155 struct sockaddr_in sockAddr;
rob@76 156 std::memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
rob@76 157 socklen_t length = sizeof(sockAddr);
rob@76 158 if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
rob@76 159 throw std::runtime_error("unable to getsockname\n");
rob@76 160 }
rob@76 161
rob@76 162 if( isConnected_ ){
rob@76 163 // reconnect to the connected address
rob@76 164
rob@76 165 if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
rob@76 166 throw std::runtime_error("unable to connect udp socket\n");
rob@76 167 }
rob@76 168
rob@76 169 }else{
rob@76 170 // unconnect from the remote address
rob@76 171
rob@76 172 struct sockaddr_in unconnectSockAddr;
rob@76 173 SockaddrFromIpEndpointName( unconnectSockAddr, IpEndpointName() );
rob@76 174
rob@76 175 if( connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr)) < 0
rob@76 176 && WSAGetLastError() != WSAEADDRNOTAVAIL ){
rob@76 177 throw std::runtime_error("unable to un-connect udp socket\n");
rob@76 178 }
rob@76 179 }
rob@76 180
rob@76 181 return IpEndpointNameFromSockaddr( sockAddr );
rob@76 182 }
rob@76 183
rob@76 184 void Connect( const IpEndpointName& remoteEndpoint )
rob@76 185 {
rob@76 186 SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
rob@76 187
rob@76 188 if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
rob@76 189 throw std::runtime_error("unable to connect udp socket\n");
rob@76 190 }
rob@76 191
rob@76 192 isConnected_ = true;
rob@76 193 }
rob@76 194
rob@76 195 void Send( const char *data, std::size_t size )
rob@76 196 {
rob@76 197 assert( isConnected_ );
rob@76 198
rob@76 199 send( socket_, data, (int)size, 0 );
rob@76 200 }
rob@76 201
rob@76 202 void SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )
rob@76 203 {
rob@76 204 sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
rob@76 205 sendToAddr_.sin_port = htons( (short)remoteEndpoint.port );
rob@76 206
rob@76 207 sendto( socket_, data, (int)size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
rob@76 208 }
rob@76 209
rob@76 210 void Bind( const IpEndpointName& localEndpoint )
rob@76 211 {
rob@76 212 struct sockaddr_in bindSockAddr;
rob@76 213 SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
rob@76 214
rob@76 215 if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
rob@76 216 throw std::runtime_error("unable to bind udp socket\n");
rob@76 217 }
rob@76 218
rob@76 219 isBound_ = true;
rob@76 220 }
rob@76 221
rob@76 222 bool IsBound() const { return isBound_; }
rob@76 223
rob@76 224 std::size_t ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )
rob@76 225 {
rob@76 226 assert( isBound_ );
rob@76 227
rob@76 228 struct sockaddr_in fromAddr;
rob@76 229 socklen_t fromAddrLen = sizeof(fromAddr);
rob@76 230
rob@76 231 int result = recvfrom(socket_, data, (int)size, 0,
rob@76 232 (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
rob@76 233 if( result < 0 )
rob@76 234 return 0;
rob@76 235
rob@76 236 remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
rob@76 237 remoteEndpoint.port = ntohs(fromAddr.sin_port);
rob@76 238
rob@76 239 return result;
rob@76 240 }
rob@76 241
rob@76 242 SOCKET& Socket() { return socket_; }
rob@76 243 };
rob@76 244
rob@76 245 UdpSocket::UdpSocket()
rob@76 246 {
rob@76 247 impl_ = new Implementation();
rob@76 248 }
rob@76 249
rob@76 250 UdpSocket::~UdpSocket()
rob@76 251 {
rob@76 252 delete impl_;
rob@76 253 }
rob@76 254
rob@76 255 void UdpSocket::SetEnableBroadcast( bool enableBroadcast )
rob@76 256 {
rob@76 257 impl_->SetEnableBroadcast( enableBroadcast );
rob@76 258 }
rob@76 259
rob@76 260 void UdpSocket::SetAllowReuse( bool allowReuse )
rob@76 261 {
rob@76 262 impl_->SetAllowReuse( allowReuse );
rob@76 263 }
rob@76 264
rob@76 265 IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
rob@76 266 {
rob@76 267 return impl_->LocalEndpointFor( remoteEndpoint );
rob@76 268 }
rob@76 269
rob@76 270 void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
rob@76 271 {
rob@76 272 impl_->Connect( remoteEndpoint );
rob@76 273 }
rob@76 274
rob@76 275 void UdpSocket::Send( const char *data, std::size_t size )
rob@76 276 {
rob@76 277 impl_->Send( data, size );
rob@76 278 }
rob@76 279
rob@76 280 void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, std::size_t size )
rob@76 281 {
rob@76 282 impl_->SendTo( remoteEndpoint, data, size );
rob@76 283 }
rob@76 284
rob@76 285 void UdpSocket::Bind( const IpEndpointName& localEndpoint )
rob@76 286 {
rob@76 287 impl_->Bind( localEndpoint );
rob@76 288 }
rob@76 289
rob@76 290 bool UdpSocket::IsBound() const
rob@76 291 {
rob@76 292 return impl_->IsBound();
rob@76 293 }
rob@76 294
rob@76 295 std::size_t UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, std::size_t size )
rob@76 296 {
rob@76 297 return impl_->ReceiveFrom( remoteEndpoint, data, size );
rob@76 298 }
rob@76 299
rob@76 300
rob@76 301 struct AttachedTimerListener{
rob@76 302 AttachedTimerListener( int id, int p, TimerListener *tl )
rob@76 303 : initialDelayMs( id )
rob@76 304 , periodMs( p )
rob@76 305 , listener( tl ) {}
rob@76 306 int initialDelayMs;
rob@76 307 int periodMs;
rob@76 308 TimerListener *listener;
rob@76 309 };
rob@76 310
rob@76 311
rob@76 312 static bool CompareScheduledTimerCalls(
rob@76 313 const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
rob@76 314 {
rob@76 315 return lhs.first < rhs.first;
rob@76 316 }
rob@76 317
rob@76 318
rob@76 319 SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
rob@76 320
rob@76 321 extern "C" /*static*/ void InterruptSignalHandler( int );
rob@76 322 /*static*/ void InterruptSignalHandler( int )
rob@76 323 {
rob@76 324 multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
rob@76 325 #ifndef WINCE
rob@76 326 signal( SIGINT, SIG_DFL );
rob@76 327 #endif
rob@76 328 }
rob@76 329
rob@76 330
rob@76 331 class SocketReceiveMultiplexer::Implementation{
rob@76 332 NetworkInitializer networkInitializer_;
rob@76 333
rob@76 334 std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
rob@76 335 std::vector< AttachedTimerListener > timerListeners_;
rob@76 336
rob@76 337 volatile bool break_;
rob@76 338 HANDLE breakEvent_;
rob@76 339
rob@76 340 double GetCurrentTimeMs() const
rob@76 341 {
rob@76 342 #ifndef WINCE
rob@76 343 return timeGetTime(); // FIXME: bad choice if you want to run for more than 40 days
rob@76 344 #else
rob@76 345 return 0;
rob@76 346 #endif
rob@76 347 }
rob@76 348
rob@76 349 public:
rob@76 350 Implementation()
rob@76 351 {
rob@76 352 breakEvent_ = CreateEvent( NULL, FALSE, FALSE, NULL );
rob@76 353 }
rob@76 354
rob@76 355 ~Implementation()
rob@76 356 {
rob@76 357 CloseHandle( breakEvent_ );
rob@76 358 }
rob@76 359
rob@76 360 void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
rob@76 361 {
rob@76 362 assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
rob@76 363 // we don't check that the same socket has been added multiple times, even though this is an error
rob@76 364 socketListeners_.push_back( std::make_pair( listener, socket ) );
rob@76 365 }
rob@76 366
rob@76 367 void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
rob@76 368 {
rob@76 369 std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i =
rob@76 370 std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
rob@76 371 assert( i != socketListeners_.end() );
rob@76 372
rob@76 373 socketListeners_.erase( i );
rob@76 374 }
rob@76 375
rob@76 376 void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
rob@76 377 {
rob@76 378 timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
rob@76 379 }
rob@76 380
rob@76 381 void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
rob@76 382 {
rob@76 383 timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
rob@76 384 }
rob@76 385
rob@76 386 void DetachPeriodicTimerListener( TimerListener *listener )
rob@76 387 {
rob@76 388 std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
rob@76 389 while( i != timerListeners_.end() ){
rob@76 390 if( i->listener == listener )
rob@76 391 break;
rob@76 392 ++i;
rob@76 393 }
rob@76 394
rob@76 395 assert( i != timerListeners_.end() );
rob@76 396
rob@76 397 timerListeners_.erase( i );
rob@76 398 }
rob@76 399
rob@76 400 void Run()
rob@76 401 {
rob@76 402 break_ = false;
rob@76 403
rob@76 404 // prepare the window events which we use to wake up on incoming data
rob@76 405 // we use this instead of select() primarily to support the AsyncBreak()
rob@76 406 // mechanism.
rob@76 407
rob@76 408 std::vector<HANDLE> events( socketListeners_.size() + 1, 0 );
rob@76 409 int j=0;
rob@76 410 for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
rob@76 411 i != socketListeners_.end(); ++i, ++j ){
rob@76 412
rob@76 413 HANDLE event = CreateEvent( NULL, FALSE, FALSE, NULL );
rob@76 414 WSAEventSelect( i->second->impl_->Socket(), event, FD_READ ); // note that this makes the socket non-blocking which is why we can safely call RecieveFrom() on all sockets below
rob@76 415 events[j] = event;
rob@76 416 }
rob@76 417
rob@76 418
rob@76 419 events[ socketListeners_.size() ] = breakEvent_; // last event in the collection is the break event
rob@76 420
rob@76 421
rob@76 422 // configure the timer queue
rob@76 423 double currentTimeMs = GetCurrentTimeMs();
rob@76 424
rob@76 425 // expiry time ms, listener
rob@76 426 std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
rob@76 427 for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
rob@76 428 i != timerListeners_.end(); ++i )
rob@76 429 timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
rob@76 430 std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
rob@76 431
rob@76 432 const int MAX_BUFFER_SIZE = 4098;
rob@76 433 char *data = new char[ MAX_BUFFER_SIZE ];
rob@76 434 IpEndpointName remoteEndpoint;
rob@76 435
rob@76 436 while( !break_ ){
rob@76 437
rob@76 438 double currentTimeMs = GetCurrentTimeMs();
rob@76 439
rob@76 440 DWORD waitTime = INFINITE;
rob@76 441 if( !timerQueue_.empty() ){
rob@76 442
rob@76 443 waitTime = (DWORD)( timerQueue_.front().first >= currentTimeMs
rob@76 444 ? timerQueue_.front().first - currentTimeMs
rob@76 445 : 0 );
rob@76 446 }
rob@76 447
rob@76 448 DWORD waitResult = WaitForMultipleObjects( (DWORD)socketListeners_.size() + 1, &events[0], FALSE, waitTime );
rob@76 449 if( break_ )
rob@76 450 break;
rob@76 451
rob@76 452 if( waitResult != WAIT_TIMEOUT ){
rob@76 453 for( int i = waitResult - WAIT_OBJECT_0; i < (int)socketListeners_.size(); ++i ){
rob@76 454 std::size_t size = socketListeners_[i].second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
rob@76 455 if( size > 0 ){
rob@76 456 socketListeners_[i].first->ProcessPacket( data, (int)size, remoteEndpoint );
rob@76 457 if( break_ )
rob@76 458 break;
rob@76 459 }
rob@76 460 }
rob@76 461 }
rob@76 462
rob@76 463 // execute any expired timers
rob@76 464 currentTimeMs = GetCurrentTimeMs();
rob@76 465 bool resort = false;
rob@76 466 for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
rob@76 467 i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
rob@76 468
rob@76 469 i->second.listener->TimerExpired();
rob@76 470 if( break_ )
rob@76 471 break;
rob@76 472
rob@76 473 i->first += i->second.periodMs;
rob@76 474 resort = true;
rob@76 475 }
rob@76 476 if( resort )
rob@76 477 std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
rob@76 478 }
rob@76 479
rob@76 480 delete [] data;
rob@76 481
rob@76 482 // free events
rob@76 483 j = 0;
rob@76 484 for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
rob@76 485 i != socketListeners_.end(); ++i, ++j ){
rob@76 486
rob@76 487 WSAEventSelect( i->second->impl_->Socket(), events[j], 0 ); // remove association between socket and event
rob@76 488 CloseHandle( events[j] );
rob@76 489 unsigned long enableNonblocking = 0;
rob@76 490 ioctlsocket( i->second->impl_->Socket(), FIONBIO, &enableNonblocking ); // make the socket blocking again
rob@76 491 }
rob@76 492 }
rob@76 493
rob@76 494 void Break()
rob@76 495 {
rob@76 496 break_ = true;
rob@76 497 }
rob@76 498
rob@76 499 void AsynchronousBreak()
rob@76 500 {
rob@76 501 break_ = true;
rob@76 502 SetEvent( breakEvent_ );
rob@76 503 }
rob@76 504 };
rob@76 505
rob@76 506
rob@76 507
rob@76 508 SocketReceiveMultiplexer::SocketReceiveMultiplexer()
rob@76 509 {
rob@76 510 impl_ = new Implementation();
rob@76 511 }
rob@76 512
rob@76 513 SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
rob@76 514 {
rob@76 515 delete impl_;
rob@76 516 }
rob@76 517
rob@76 518 void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
rob@76 519 {
rob@76 520 impl_->AttachSocketListener( socket, listener );
rob@76 521 }
rob@76 522
rob@76 523 void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
rob@76 524 {
rob@76 525 impl_->DetachSocketListener( socket, listener );
rob@76 526 }
rob@76 527
rob@76 528 void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
rob@76 529 {
rob@76 530 impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
rob@76 531 }
rob@76 532
rob@76 533 void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
rob@76 534 {
rob@76 535 impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
rob@76 536 }
rob@76 537
rob@76 538 void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
rob@76 539 {
rob@76 540 impl_->DetachPeriodicTimerListener( listener );
rob@76 541 }
rob@76 542
rob@76 543 void SocketReceiveMultiplexer::Run()
rob@76 544 {
rob@76 545 impl_->Run();
rob@76 546 }
rob@76 547
rob@76 548 void SocketReceiveMultiplexer::RunUntilSigInt()
rob@76 549 {
rob@76 550 assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
rob@76 551 multiplexerInstanceToAbortWithSigInt_ = this;
rob@76 552 #ifndef WINCE
rob@76 553 signal( SIGINT, InterruptSignalHandler );
rob@76 554 #endif
rob@76 555 impl_->Run();
rob@76 556 #ifndef WINCE
rob@76 557 signal( SIGINT, SIG_DFL );
rob@76 558 #endif
rob@76 559 multiplexerInstanceToAbortWithSigInt_ = 0;
rob@76 560 }
rob@76 561
rob@76 562 void SocketReceiveMultiplexer::Break()
rob@76 563 {
rob@76 564 impl_->Break();
rob@76 565 }
rob@76 566
rob@76 567 void SocketReceiveMultiplexer::AsynchronousBreak()
rob@76 568 {
rob@76 569 impl_->AsynchronousBreak();
rob@76 570 }
rob@76 571