summaryrefslogtreecommitdiff
path: root/Sockets/UdpSocket.h
blob: a4561727c612a4df370517eb4dd3644aa9febe87 (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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/** \file UdpSocket.h
 **	\date  2004-02-13
 **	\author grymse@alhem.net
**/
/*
Copyright (C) 2004-2007  Anders Hedstrom

This library is made available under the terms of the GNU GPL.

If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program 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 General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#ifndef _SOCKETS_UdpSocket_H
#define _SOCKETS_UdpSocket_H

#include "sockets-config.h"
#include "Socket.h"

#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif

/** Socket implementation for UDP.
	\ingroup basic */
class UdpSocket : public Socket
{
public:
	/** Constructor.
		\param h ISocketHandler reference
		\param ibufsz Maximum size of receive message (extra bytes will be truncated)
		\param ipv6 'true' if this is an ipv6 socket */
	UdpSocket(ISocketHandler& h,int ibufsz = 16384,bool ipv6 = false, int retries = 0);
	~UdpSocket();

	/** Called when incoming data has been received.
		\param buf Pointer to data
		\param len Length of data
		\param sa Pointer to sockaddr struct of sender
		\param sa_len Length of sockaddr struct */
	virtual void OnRawData(const char *buf,size_t len,struct sockaddr *sa,socklen_t sa_len);

	/** Called when incoming data has been received and read timestamp is enabled.
		\param buf Pointer to data
		\param len Length of data
		\param sa Pointer to sockaddr struct of sender
		\param sa_len Length of sockaddr struct
		\param ts Timestamp from message */
	virtual void OnRawData(const char *buf,size_t len,struct sockaddr *sa,socklen_t sa_len,struct timeval *ts);

	/** To receive incoming data, call Bind to setup an incoming port.
		\param port Incoming port number
		\param range Port range to try if ports already in use
		\return 0 if bind succeeded */
	int Bind(port_t& port,int range = 1);
	/** To receive data on a specific interface:port, use this.
		\param intf Interface ip/hostname
		\param port Port number
		\param range Port range
		\return 0 if bind succeeded */
	int Bind(const std::string& intf,port_t& port,int range = 1);
	/** To receive data on a specific interface:port, use this.
		\param a Ip address
		\param port Port number
		\param range Port range
		\return 0 if bind succeeded */
	int Bind(ipaddr_t a,port_t& port,int range = 1);
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	/** To receive data on a specific interface:port, use this.
		\param a Ipv6 address
		\param port Port number
		\param range Port range
		\return 0 if bind succeeded */
	int Bind(in6_addr a,port_t& port,int range = 1);
#endif
#endif
	/** To receive data on a specific interface:port, use this.
		\param ad Socket address
		\param range Port range
		\return 0 if bind succeeded */
	int Bind(SocketAddress& ad,int range = 1);

	/** Define remote host.
		\param l Address of remote host
		\param port Port of remote host
		\return true if successful */
	bool Open(ipaddr_t l,port_t port);
	/** Define remote host.
		\param host Hostname
		\param port Port number
		\return true if successful */
	bool Open(const std::string& host,port_t port);
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	/** Define remote host.
		\param a Address of remote host, ipv6
		\param port Port of remote host
		\return true if successful */
	bool Open(struct in6_addr& a,port_t port);
#endif
#endif
	/** Define remote host.
		\param ad Socket address
		\return true if successful */
	bool Open(SocketAddress& ad);

	/** Send to specified host */
	void SendToBuf(const std::string& ,port_t,const char *data,int len,int flags = 0);
	/** Send to specified address */
	void SendToBuf(ipaddr_t,port_t,const char *data,int len,int flags = 0);
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	/** Send to specified ipv6 address */
	void SendToBuf(in6_addr,port_t,const char *data,int len,int flags = 0);
#endif
#endif
	/** Send to specified socket address */
	void SendToBuf(SocketAddress& ad,const char *data,int len,int flags = 0);

	/** Send string to specified host */
	void SendTo(const std::string&,port_t,const std::string&,int flags = 0);
	/** Send string to specified address */
	void SendTo(ipaddr_t,port_t,const std::string&,int flags = 0);
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	/** Send string to specified ipv6 address */
	void SendTo(in6_addr,port_t,const std::string&,int flags = 0);
#endif
#endif
	/** Send string to specified socket address */
	void SendTo(SocketAddress& ad,const std::string&,int flags = 0);

	/** Send to connected address */
	void SendBuf(const char *data,size_t,int flags = 0);
	/** Send string to connected address. */
	void Send(const std::string& ,int flags = 0);

	/** Set broadcast */
	void SetBroadcast(bool b = true);
	/** Check broadcast flag.
		\return true broadcast is enabled. */
	bool IsBroadcast();

	/** multicast */
	void SetMulticastTTL(int ttl = 1);
	int GetMulticastTTL();
	void SetMulticastLoop(bool = true);
	bool IsMulticastLoop();
	void AddMulticastMembership(const std::string& group,const std::string& intf = "0.0.0.0",int if_index = 0);
	void DropMulticastMembership(const std::string& group,const std::string& intf = "0.0.0.0",int if_index = 0);
#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
	/** multicast, ipv6 only */
	void SetMulticastHops(int = -1);
	/** multicast, ipv6 only */
	int GetMulticastHops();
#endif
#endif
	/** Returns true if Bind succeeded. */
	bool IsBound();
	/** Return Bind port number */
	port_t GetPort();

	void OnOptions(int,int,int,SOCKET) {}

	int GetLastSizeWritten();

	/** Also read timestamp information from incoming message */
	void SetTimestamp(bool = true);

protected:
	UdpSocket(const UdpSocket& s) : Socket(s) {}
	void OnRead();
#ifndef _WIN32
	/** This method emulates socket recvfrom, but uses messages so we can get the timestamp */
	int ReadTS(char *ioBuf, int inBufSize, struct sockaddr *from, socklen_t fromlen, struct timeval *ts);
#endif

private:
	UdpSocket& operator=(const UdpSocket& ) { return *this; }
	/** create before using sendto methods */
	void CreateConnection();
	char *m_ibuf; ///< Input buffer
	int m_ibufsz; ///< Size of input buffer
	bool m_bind_ok; ///< Bind completed successfully
	port_t m_port; ///< Bind port number
	int m_last_size_written;
	int m_retries;
	bool m_b_read_ts;
};


#ifdef SOCKETS_NAMESPACE
}
#endif

#endif // _SOCKETS_UdpSocket_H