File: UDPListener.h

package info (click to toggle)
spring 104.0%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 47,512 kB
  • sloc: cpp: 391,093; ansic: 79,943; python: 12,356; java: 12,201; awk: 5,889; sh: 1,826; xml: 655; makefile: 486; perl: 405; php: 211; objc: 194; sed: 2
file content (99 lines) | stat: -rw-r--r-- 2,885 bytes parent folder | download
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
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */

#ifndef _UDP_LISTENER_H
#define _UDP_LISTENER_H

#include "System/Misc/NonCopyable.h"
#include <memory>
#include <asio/ip/udp.hpp>
#include <map>
#include <queue>
#include <string>

namespace netcode
{
class UDPConnection;
typedef std::shared_ptr<asio::ip::udp::socket> SocketPtr;

/**
 * @brief Class for handling Connections on an UDPSocket
 * Use this class if you want to use a UDPSocket to connect to more than
 * one client.
 * You can Listen for new connections, initiate new ones and send/recieve data
 * to/from them.
 */
class UDPListener : spring::noncopyable
{
public:
	/**
	 * @brief Open a socket and make it ready for listening
	 * @param  port the port to bind the socket to
	 * @param  ip local IP to bind to, or "" for any
	 */
	UDPListener(int port, const std::string& ip = "");

	/**
	 * @brief close the socket and DELETE all connections
	 */
	~UDPListener();

	/**
	 * Try to bind a socket to a local address and port.
	 * If no IP or an empty one is given, this method will use
	 * the IP v6 any address "::", if IP v6 is supported.
	 * @param  port the port to bind the socket to
	 * @param  socket the socket to be bound
	 * @param  ip local IP (v4 or v6) to bind to,
	 *         the default value "" results in the v6 any address "::",
	 *         or the v4 equivalent "0.0.0.0", if v6 is no supported
	 */
	static std::string TryBindSocket(int port, SocketPtr* socket, const std::string& ip = "");

	/**
	 * @brief Run this from time to time
	 * Recieve data from the socket and hand it to the associated UDPConnection,
	 * or open a new UDPConnection. It also Updates all of its connections.
	 */
	void Update();

	/**
	 * @brief Initiate a connection
	 * Make a new connection to ip:port. It will be pushed back in conn.
	 */
	std::shared_ptr<UDPConnection> SpawnConnection(const std::string& ip, const unsigned port);

	/**
	 * Set if we are accepting new connections
	 * or drop all data from unconnected addresses.
	 */
	void SetAcceptingConnections(const bool enable);
	bool IsAcceptingConnections() const;
	bool HasIncomingConnections() const;

	std::weak_ptr<UDPConnection> PreviewConnection();
	std::shared_ptr<UDPConnection> AcceptConnection();

	void RejectConnection();
	void UpdateConnections(); // Updates connections when the endpoint has been reconnected

private:
	/**
	 * @brief Do we accept packets from unknown sources?
	 * If true, we will create a new connection, if false, they get dropped.
	 */
	bool acceptNewConnections;

	/// Our socket
	/// typedef std::shared_ptr<asio::ip::udp::socket> SocketPtr;
	SocketPtr mySocket;

	/// all connections
	std::map< asio::ip::udp::endpoint, std::weak_ptr<UDPConnection> > connMap;
	std::map< std::string, size_t> dropMap;

	std::queue< std::shared_ptr<UDPConnection> > waiting;
};

}

#endif // _UDP_LISTENER_H