annotate trunk/external/oscpack/ip/win32/UdpSocket.cpp @ 706:f8e90b5d85fd tip

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