File: UDPListener.h

package info (click to toggle)
spring 105.0.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 108,860 kB
  • sloc: cpp: 467,785; ansic: 302,607; python: 12,925; java: 12,201; awk: 5,889; sh: 2,371; xml: 655; perl: 405; php: 276; objc: 194; makefile: 75; sed: 2
file content (99 lines) | stat: -rw-r--r-- 3,015 bytes parent folder | download | duplicates (3)
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;

/**
 * @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, std::shared_ptr<asio::ip::udp::socket>& sock, 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();

	/**
	 * Set if we are accepting new connections
	 * or drop all data from unconnected addresses.
	 */
	void SetAcceptingConnections(const bool enable) { acceptNewConnections = enable; }
	bool IsAcceptingConnections() const { return acceptNewConnections; }
	bool HasIncomingConnections() const { return (!waiting.empty()); }

	/**
	 * @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);

	std::weak_ptr<UDPConnection> PreviewConnection() { return (waiting.front()); }
	std::shared_ptr<UDPConnection> AcceptConnection();

	void RejectConnection() { waiting.pop(); }
	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;

	/// socket being listened on
	std::shared_ptr<asio::ip::udp::socket> socket;

	std::vector<std::uint8_t> recvBuffer;

	/// 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