front_idill/extern/fajran-npTuioClient/TuioClient/oscpack/ip/posix/UdpSocket.cpp
author bastiena
Fri, 06 Apr 2012 10:44:54 +0200
changeset 21 e4e5f02787a1
permissions -rw-r--r--
Front IDILL : Added Communication extern named fajran-npTuioClient It contains the project generating a dll used as a browser plugin.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
21
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     1
/*
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     2
	oscpack -- Open Sound Control packet manipulation library
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     3
	http://www.audiomulch.com/~rossb/oscpack
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     4
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     5
	Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     6
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     7
	Permission is hereby granted, free of charge, to any person obtaining
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     8
	a copy of this software and associated documentation files
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
     9
	(the "Software"), to deal in the Software without restriction,
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    10
	including without limitation the rights to use, copy, modify, merge,
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    11
	publish, distribute, sublicense, and/or sell copies of the Software,
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    12
	and to permit persons to whom the Software is furnished to do so,
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    13
	subject to the following conditions:
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    14
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    15
	The above copyright notice and this permission notice shall be
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    16
	included in all copies or substantial portions of the Software.
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    17
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    18
	Any person wishing to distribute modifications to the Software is
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    19
	requested to send the modifications to the original developer so that
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    20
	they can be incorporated into the canonical version.
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    21
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    22
	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    23
	EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    24
	MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    25
	IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    26
	ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    27
	CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    28
	WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    29
*/
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    30
#include "ip/UdpSocket.h"
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    31
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    32
#include <vector>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    33
#include <algorithm>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    34
#include <stdexcept>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    35
#include <assert.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    36
#include <signal.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    37
#include <math.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    38
#include <errno.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    39
#include <string.h> // for memset
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    40
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    41
#include <pthread.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    42
#include <unistd.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    43
#include <stdlib.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    44
#include <stdio.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    45
#include <netdb.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    46
#include <sys/types.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    47
#include <sys/socket.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    48
#include <sys/time.h>
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    49
#include <netinet/in.h> // for sockaddr_in
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    50
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    51
#include "ip/PacketListener.h"
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    52
#include "ip/TimerListener.h"
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    53
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    54
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    55
#if defined(__APPLE__) && !defined(_SOCKLEN_T)
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    56
// pre system 10.3 didn have socklen_t
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    57
typedef ssize_t socklen_t;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    58
#endif
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    59
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    60
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    61
static void SockaddrFromIpEndpointName( struct sockaddr_in& sockAddr, const IpEndpointName& endpoint )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    62
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    63
    memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    64
    sockAddr.sin_family = AF_INET;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    65
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    66
	sockAddr.sin_addr.s_addr = 
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    67
		(endpoint.address == IpEndpointName::ANY_ADDRESS)
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    68
		? INADDR_ANY
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    69
		: htonl( endpoint.address );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    70
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    71
	sockAddr.sin_port =
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    72
		(endpoint.port == IpEndpointName::ANY_PORT)
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    73
		? 0
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    74
		: htons( endpoint.port );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    75
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    76
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    77
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    78
static IpEndpointName IpEndpointNameFromSockaddr( const struct sockaddr_in& sockAddr )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    79
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    80
	return IpEndpointName( 
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    81
		(sockAddr.sin_addr.s_addr == INADDR_ANY) 
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    82
			? IpEndpointName::ANY_ADDRESS 
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    83
			: ntohl( sockAddr.sin_addr.s_addr ),
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    84
		(sockAddr.sin_port == 0)
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    85
			? IpEndpointName::ANY_PORT
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    86
			: ntohs( sockAddr.sin_port )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    87
		);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    88
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    89
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    90
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    91
class UdpSocket::Implementation{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    92
	bool isBound_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    93
	bool isConnected_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    94
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    95
	int socket_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    96
	struct sockaddr_in connectedAddr_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    97
	struct sockaddr_in sendToAddr_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    98
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
    99
public:
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   100
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   101
	Implementation()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   102
		: isBound_( false )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   103
		, isConnected_( false )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   104
		, socket_( -1 )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   105
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   106
		if( (socket_ = socket( AF_INET, SOCK_DGRAM, 0 )) == -1 ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   107
            throw std::runtime_error("unable to create udp socket\n");
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   108
        }
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   109
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   110
		memset( &sendToAddr_, 0, sizeof(sendToAddr_) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   111
        sendToAddr_.sin_family = AF_INET;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   112
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   113
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   114
	~Implementation()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   115
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   116
		if (socket_ != -1) close(socket_);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   117
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   118
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   119
	IpEndpointName LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   120
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   121
		assert( isBound_ );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   122
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   123
		// first connect the socket to the remote server
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   124
        
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   125
        struct sockaddr_in connectSockAddr;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   126
		SockaddrFromIpEndpointName( connectSockAddr, remoteEndpoint );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   127
       
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   128
        if (connect(socket_, (struct sockaddr *)&connectSockAddr, sizeof(connectSockAddr)) < 0) {
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   129
            throw std::runtime_error("unable to connect udp socket\n");
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   130
        }
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   131
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   132
        // get the address
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   133
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   134
        struct sockaddr_in sockAddr;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   135
        memset( (char *)&sockAddr, 0, sizeof(sockAddr ) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   136
        socklen_t length = sizeof(sockAddr);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   137
        if (getsockname(socket_, (struct sockaddr *)&sockAddr, &length) < 0) {
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   138
            throw std::runtime_error("unable to getsockname\n");
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   139
        }
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   140
        
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   141
		if( isConnected_ ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   142
			// reconnect to the connected address
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   143
			
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   144
			if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   145
				throw std::runtime_error("unable to connect udp socket\n");
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   146
			}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   147
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   148
		}else{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   149
			// unconnect from the remote address
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   150
		
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   151
			struct sockaddr_in unconnectSockAddr;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   152
			memset( (char *)&unconnectSockAddr, 0, sizeof(unconnectSockAddr ) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   153
			unconnectSockAddr.sin_family = AF_UNSPEC;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   154
			// address fields are zero
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   155
			int connectResult = connect(socket_, (struct sockaddr *)&unconnectSockAddr, sizeof(unconnectSockAddr));
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   156
			if ( connectResult < 0 && errno != EAFNOSUPPORT ) {
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   157
				throw std::runtime_error("unable to un-connect udp socket\n");
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   158
			}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   159
		}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   160
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   161
		return IpEndpointNameFromSockaddr( sockAddr );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   162
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   163
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   164
	void Connect( const IpEndpointName& remoteEndpoint )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   165
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   166
		SockaddrFromIpEndpointName( connectedAddr_, remoteEndpoint );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   167
       
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   168
        if (connect(socket_, (struct sockaddr *)&connectedAddr_, sizeof(connectedAddr_)) < 0) {
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   169
            throw std::runtime_error("unable to connect udp socket\n");
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   170
        }
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   171
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   172
		isConnected_ = true;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   173
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   174
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   175
	void Send( const char *data, int size )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   176
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   177
		assert( isConnected_ );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   178
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   179
        send( socket_, data, size, 0 );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   180
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   181
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   182
    void SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   183
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   184
		sendToAddr_.sin_addr.s_addr = htonl( remoteEndpoint.address );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   185
        sendToAddr_.sin_port = htons( remoteEndpoint.port );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   186
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   187
        sendto( socket_, data, size, 0, (sockaddr*)&sendToAddr_, sizeof(sendToAddr_) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   188
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   189
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   190
	void Bind( const IpEndpointName& localEndpoint )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   191
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   192
		struct sockaddr_in bindSockAddr;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   193
		SockaddrFromIpEndpointName( bindSockAddr, localEndpoint );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   194
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   195
        if (bind(socket_, (struct sockaddr *)&bindSockAddr, sizeof(bindSockAddr)) < 0) {
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   196
            throw std::runtime_error("unable to bind udp socket\n");
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   197
        }
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   198
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   199
		isBound_ = true;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   200
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   201
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   202
	bool IsBound() const { return isBound_; }
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   203
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   204
    int ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   205
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   206
		assert( isBound_ );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   207
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   208
		struct sockaddr_in fromAddr;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   209
        socklen_t fromAddrLen = sizeof(fromAddr);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   210
             	 
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   211
        int result = recvfrom(socket_, data, size, 0,
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   212
                    (struct sockaddr *) &fromAddr, (socklen_t*)&fromAddrLen);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   213
		if( result < 0 )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   214
			return 0;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   215
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   216
		remoteEndpoint.address = ntohl(fromAddr.sin_addr.s_addr);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   217
		remoteEndpoint.port = ntohs(fromAddr.sin_port);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   218
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   219
		return result;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   220
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   221
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   222
	int Socket() { return socket_; }
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   223
};
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   224
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   225
UdpSocket::UdpSocket()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   226
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   227
	impl_ = new Implementation();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   228
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   229
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   230
UdpSocket::~UdpSocket()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   231
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   232
	delete impl_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   233
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   234
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   235
IpEndpointName UdpSocket::LocalEndpointFor( const IpEndpointName& remoteEndpoint ) const
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   236
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   237
	return impl_->LocalEndpointFor( remoteEndpoint );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   238
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   239
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   240
void UdpSocket::Connect( const IpEndpointName& remoteEndpoint )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   241
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   242
	impl_->Connect( remoteEndpoint );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   243
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   244
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   245
void UdpSocket::Send( const char *data, int size )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   246
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   247
	impl_->Send( data, size );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   248
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   249
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   250
void UdpSocket::SendTo( const IpEndpointName& remoteEndpoint, const char *data, int size )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   251
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   252
	impl_->SendTo( remoteEndpoint, data, size );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   253
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   254
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   255
void UdpSocket::Bind( const IpEndpointName& localEndpoint )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   256
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   257
	impl_->Bind( localEndpoint );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   258
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   259
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   260
bool UdpSocket::IsBound() const
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   261
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   262
	return impl_->IsBound();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   263
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   264
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   265
int UdpSocket::ReceiveFrom( IpEndpointName& remoteEndpoint, char *data, int size )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   266
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   267
	return impl_->ReceiveFrom( remoteEndpoint, data, size );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   268
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   269
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   270
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   271
struct AttachedTimerListener{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   272
	AttachedTimerListener( int id, int p, TimerListener *tl )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   273
		: initialDelayMs( id )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   274
		, periodMs( p )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   275
		, listener( tl ) {}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   276
	int initialDelayMs;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   277
	int periodMs;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   278
	TimerListener *listener;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   279
};
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   280
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   281
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   282
static bool CompareScheduledTimerCalls( 
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   283
		const std::pair< double, AttachedTimerListener > & lhs, const std::pair< double, AttachedTimerListener > & rhs )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   284
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   285
	return lhs.first < rhs.first;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   286
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   287
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   288
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   289
SocketReceiveMultiplexer *multiplexerInstanceToAbortWithSigInt_ = 0;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   290
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   291
extern "C" /*static*/ void InterruptSignalHandler( int );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   292
/*static*/ void InterruptSignalHandler( int )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   293
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   294
	multiplexerInstanceToAbortWithSigInt_->AsynchronousBreak();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   295
	signal( SIGINT, SIG_DFL );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   296
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   297
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   298
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   299
class SocketReceiveMultiplexer::Implementation{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   300
	std::vector< std::pair< PacketListener*, UdpSocket* > > socketListeners_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   301
	std::vector< AttachedTimerListener > timerListeners_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   302
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   303
	volatile bool break_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   304
	int breakPipe_[2]; // [0] is the reader descriptor and [1] the writer
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   305
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   306
	double GetCurrentTimeMs() const
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   307
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   308
		struct timeval t;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   309
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   310
		gettimeofday( &t, 0 );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   311
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   312
		return ((double)t.tv_sec*1000.) + ((double)t.tv_usec / 1000.);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   313
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   314
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   315
public:
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   316
    Implementation()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   317
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   318
		if( pipe(breakPipe_) != 0 )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   319
			throw std::runtime_error( "creation of asynchronous break pipes failed\n" );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   320
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   321
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   322
    ~Implementation()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   323
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   324
		close( breakPipe_[0] );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   325
		close( breakPipe_[1] );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   326
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   327
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   328
    void AttachSocketListener( UdpSocket *socket, PacketListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   329
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   330
		assert( std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) ) == socketListeners_.end() );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   331
		// we don't check that the same socket has been added multiple times, even though this is an error
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   332
		socketListeners_.push_back( std::make_pair( listener, socket ) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   333
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   334
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   335
    void DetachSocketListener( UdpSocket *socket, PacketListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   336
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   337
		std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = 
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   338
				std::find( socketListeners_.begin(), socketListeners_.end(), std::make_pair(listener, socket) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   339
		assert( i != socketListeners_.end() );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   340
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   341
		socketListeners_.erase( i );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   342
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   343
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   344
    void AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   345
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   346
		timerListeners_.push_back( AttachedTimerListener( periodMilliseconds, periodMilliseconds, listener ) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   347
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   348
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   349
	void AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   350
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   351
		timerListeners_.push_back( AttachedTimerListener( initialDelayMilliseconds, periodMilliseconds, listener ) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   352
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   353
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   354
    void DetachPeriodicTimerListener( TimerListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   355
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   356
		std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   357
		while( i != timerListeners_.end() ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   358
			if( i->listener == listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   359
				break;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   360
			++i;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   361
		}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   362
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   363
		assert( i != timerListeners_.end() );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   364
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   365
		timerListeners_.erase( i );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   366
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   367
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   368
    void Run()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   369
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   370
		break_ = false;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   371
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   372
		// configure the master fd_set for select()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   373
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   374
		fd_set masterfds, tempfds;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   375
		FD_ZERO( &masterfds );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   376
		FD_ZERO( &tempfds );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   377
		
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   378
		// in addition to listening to the inbound sockets we
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   379
		// also listen to the asynchronous break pipe, so that AsynchronousBreak()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   380
		// can break us out of select() from another thread.
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   381
		FD_SET( breakPipe_[0], &masterfds );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   382
		int fdmax = breakPipe_[0];		
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   383
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   384
		for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   385
				i != socketListeners_.end(); ++i ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   386
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   387
			if( fdmax < i->second->impl_->Socket() )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   388
				fdmax = i->second->impl_->Socket();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   389
			FD_SET( i->second->impl_->Socket(), &masterfds );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   390
		}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   391
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   392
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   393
		// configure the timer queue
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   394
		double currentTimeMs = GetCurrentTimeMs();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   395
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   396
		// expiry time ms, listener
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   397
		std::vector< std::pair< double, AttachedTimerListener > > timerQueue_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   398
		for( std::vector< AttachedTimerListener >::iterator i = timerListeners_.begin();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   399
				i != timerListeners_.end(); ++i )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   400
			timerQueue_.push_back( std::make_pair( currentTimeMs + i->initialDelayMs, *i ) );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   401
		std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   402
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   403
		const int MAX_BUFFER_SIZE = 4098;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   404
		char *data = new char[ MAX_BUFFER_SIZE ];
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   405
		IpEndpointName remoteEndpoint;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   406
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   407
		struct timeval timeout;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   408
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   409
		while( !break_ ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   410
			tempfds = masterfds;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   411
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   412
			struct timeval *timeoutPtr = 0;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   413
			if( !timerQueue_.empty() ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   414
				double timeoutMs = timerQueue_.front().first - GetCurrentTimeMs();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   415
				if( timeoutMs < 0 )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   416
					timeoutMs = 0;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   417
			
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   418
				// 1000000 microseconds in a second
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   419
				timeout.tv_sec = (long)(timeoutMs * .001);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   420
				timeout.tv_usec = (long)((timeoutMs - (timeout.tv_sec * 1000)) * 1000);
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   421
				timeoutPtr = &timeout;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   422
			}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   423
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   424
			if( select( fdmax + 1, &tempfds, 0, 0, timeoutPtr ) < 0 && errno != EINTR ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   425
   				if (!break_) throw std::runtime_error("select failed\n");
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   426
				else break;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   427
			}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   428
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   429
			if ( FD_ISSET( breakPipe_[0], &tempfds ) ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   430
				// clear pending data from the asynchronous break pipe
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   431
				char c;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   432
				ssize_t ret; 
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   433
				ret = read( breakPipe_[0], &c, 1 );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   434
			}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   435
			
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   436
			if( break_ )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   437
				break;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   438
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   439
			for( std::vector< std::pair< PacketListener*, UdpSocket* > >::iterator i = socketListeners_.begin();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   440
					i != socketListeners_.end(); ++i ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   441
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   442
				if( FD_ISSET( i->second->impl_->Socket(), &tempfds ) ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   443
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   444
					int size = i->second->ReceiveFrom( remoteEndpoint, data, MAX_BUFFER_SIZE );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   445
					if( size > 0 ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   446
						i->first->ProcessPacket( data, size, remoteEndpoint );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   447
						if( break_ )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   448
							break;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   449
					}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   450
				}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   451
			}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   452
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   453
			// execute any expired timers
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   454
			currentTimeMs = GetCurrentTimeMs();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   455
			bool resort = false;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   456
			for( std::vector< std::pair< double, AttachedTimerListener > >::iterator i = timerQueue_.begin();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   457
					i != timerQueue_.end() && i->first <= currentTimeMs; ++i ){
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   458
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   459
				i->second.listener->TimerExpired();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   460
				if( break_ )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   461
					break;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   462
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   463
				i->first += i->second.periodMs;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   464
				resort = true;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   465
			}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   466
			if( resort )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   467
				std::sort( timerQueue_.begin(), timerQueue_.end(), CompareScheduledTimerCalls );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   468
		}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   469
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   470
		delete [] data;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   471
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   472
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   473
    void Break()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   474
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   475
		break_ = true;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   476
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   477
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   478
    void AsynchronousBreak()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   479
	{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   480
		break_ = true;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   481
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   482
		// Send a termination message to the asynchronous break pipe, so select() will return
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   483
		ssize_t ret;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   484
		ret = write( breakPipe_[1], "!", 1 );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   485
	}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   486
};
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   487
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   488
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   489
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   490
SocketReceiveMultiplexer::SocketReceiveMultiplexer()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   491
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   492
	impl_ = new Implementation();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   493
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   494
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   495
SocketReceiveMultiplexer::~SocketReceiveMultiplexer()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   496
{	
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   497
	delete impl_;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   498
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   499
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   500
void SocketReceiveMultiplexer::AttachSocketListener( UdpSocket *socket, PacketListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   501
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   502
	impl_->AttachSocketListener( socket, listener );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   503
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   504
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   505
void SocketReceiveMultiplexer::DetachSocketListener( UdpSocket *socket, PacketListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   506
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   507
	impl_->DetachSocketListener( socket, listener );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   508
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   509
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   510
void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int periodMilliseconds, TimerListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   511
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   512
	impl_->AttachPeriodicTimerListener( periodMilliseconds, listener );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   513
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   514
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   515
void SocketReceiveMultiplexer::AttachPeriodicTimerListener( int initialDelayMilliseconds, int periodMilliseconds, TimerListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   516
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   517
	impl_->AttachPeriodicTimerListener( initialDelayMilliseconds, periodMilliseconds, listener );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   518
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   519
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   520
void SocketReceiveMultiplexer::DetachPeriodicTimerListener( TimerListener *listener )
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   521
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   522
	impl_->DetachPeriodicTimerListener( listener );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   523
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   524
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   525
void SocketReceiveMultiplexer::Run()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   526
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   527
	impl_->Run();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   528
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   529
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   530
void SocketReceiveMultiplexer::RunUntilSigInt()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   531
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   532
	assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   533
	multiplexerInstanceToAbortWithSigInt_ = this;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   534
	signal( SIGINT, InterruptSignalHandler );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   535
	impl_->Run();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   536
	signal( SIGINT, SIG_DFL );
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   537
	multiplexerInstanceToAbortWithSigInt_ = 0;
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   538
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   539
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   540
void SocketReceiveMultiplexer::Break()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   541
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   542
	impl_->Break();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   543
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   544
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   545
void SocketReceiveMultiplexer::AsynchronousBreak()
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   546
{
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   547
	impl_->AsynchronousBreak();
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   548
}
e4e5f02787a1 Front IDILL :
bastiena
parents:
diff changeset
   549