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