summaryrefslogtreecommitdiffstats
path: root/3rdparty/openpgm-svn-r1085/pgm/include/pgm/pgm_socket.hh
blob: 9a3f11b008520218a97640e612ee8b20447878fe (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* vim:ts=8:sts=4:sw=4:noai:noexpandtab
 * 
 * PGM socket
 *
 * Copyright (c) 2010 Miru Limited.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __PGM_SOCKET_HH__
#define __PGM_SOCKET_HH__

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
#	pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)

#include <cerrno>
#ifndef _WIN32
#	include <cstddef>
#	include <sys/socket.h>
#else
#	include <ws2tcpip.h>
#endif

namespace cpgm {
#define restrict
#include <pgm/pgm.h>
};

template <typename Protocol>
class pgm_socket
{
public:
	/// The protocol type.
	typedef Protocol protocol_type;

	/// The endpoint type.
	typedef typename Protocol::endpoint endpoint_type;

	/// The native socket type.
	typedef struct cpgm::pgm_sock_t* native_type;

	/// Construct a pgm_socket without opening it.
	pgm_socket()
	{
	}

	// Open a new PGM socket implementation.
	bool open (::sa_family_t family, int sock_type, int protocol, cpgm::pgm_error_t** error)
	{
		return cpgm::pgm_socket (&this->native_type_, family, sock_type, protocol, error);
	}

	/// Close a PGM socket implementation.
	bool close (bool flush)
	{
		return pgm_close (this->native_type_, flush);
	}

	/// Get the native socket implementation.
	native_type native (void)
	{
		return this->native_type_;
	}

	// Bind the datagram socket to the specified local endpoint.
	bool bind (const endpoint_type& addr, cpgm::pgm_error_t** error)
	{
		return pgm_bind (this->native_type_, addr.data(), sizeof(addr.data()), error);
	}

	/// Connect the PGM socket to the specified endpoint.
	bool connect (cpgm::pgm_error_t** error)
	{
		return pgm_connect (this->native_type_, error);
	}

	/// Set a socket option.
	bool set_option (int optname, const void* optval, ::socklen_t optlen)
	{
		return pgm_setsockopt (this->native_type_, optname, optval, optlen);
	}

	/// Get a socket option.
	bool get_option (int optname, void* optval, ::socklen_t* optlen)
	{
		return pgm_getsockopt (this->native_type_, optname, optval, optlen);
	}

	/// Get the local endpoint.
	endpoint_type local_endpoint() const
	{
		endpoint_type endpoint;
		pgm_getsockname (this->native_type_, &endpoint);
		return endpoint;
	}

	/// Disable sends or receives on the socket.
	bool shutdown (int what)
	{
		int optname, v = 1;
#ifndef _WIN32
		if (SHUT_RD == what)		optname = cpgm::PGM_SEND_ONLY;
		else if (SHUT_WR == what)	optname = cpgm::PGM_RECV_ONLY;
#else
		if (SD_RECEIVE == what)		optname = cpgm::PGM_SEND_ONLY;
		else if (SD_SEND == what)	optname = cpgm::PGM_RECV_ONLY;
#endif
		else {
			errno = EINVAL;
			return false;
		}
		return pgm_setsockopt (this->native_type_, optname, v, sizeof(v));
	}

	/// Send some data on a connected socket.
	int send (const void* buf, std::size_t len, std::size_t* bytes_sent)
	{
		return pgm_send (this->native_type_, buf, len, bytes_sent);
	}

	/// Receive some data from the peer.
	int receive (void* buf, std::size_t len, int flags, std::size_t* bytes_read, cpgm::pgm_error_t** error)
	{
		return pgm_recv (this->native_type_, buf, len, flags, bytes_read, error);
	}

	/// Receive a datagram with the endpoint of the sender.
	int receive_from (void* buf, std::size_t len, int flags, std::size_t* bytes_read, endpoint_type* from, cpgm::pgm_error_t** error)
	{
		int ec;
		struct cpgm::pgm_sockaddr_t addr;
		socklen_t addrlen = sizeof (addr);
		ec = pgm_recvfrom (this->native_type_, buf, len, flags, bytes_read, &addr, &addrlen, error);
		from->port (addr.sa_port);
		from->address (addr.sa_addr);
/* TODO: set data-destination port */
		return ec;
	}

private:
	native_type native_type_;
};

#endif /* __PGM_SOCKET_HH__ */