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