summaryrefslogtreecommitdiffstats
path: root/src/OSSupport/ServerHandleImpl.h
blob: af06d971f238588467629f29d8ced494ca17b2de (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

// ServerHandleImpl.h

// Declares the cServerHandleImpl class implementing the TCP server functionality

// This is an internal header, no-one outside OSSupport should need to include it; use Network.h instead





#pragma once

#include "Network.h"
#include <event2/listener.h>
#include "CriticalSection.h"





// fwd:
class cTCPLinkImpl;
typedef std::shared_ptr<cTCPLinkImpl> cTCPLinkImplPtr;
typedef std::vector<cTCPLinkImplPtr> cTCPLinkImplPtrs;
class cServerHandleImpl;
typedef std::shared_ptr<cServerHandleImpl> cServerHandleImplPtr;
typedef std::vector<cServerHandleImplPtr> cServerHandleImplPtrs;





class cServerHandleImpl : public cServerHandle
{
	using Super = cServerHandle;
	friend class cTCPLinkImpl;

  public:
	/** Closes the server, dropping all the connections. */
	virtual ~cServerHandleImpl() override;

	/** Creates a new server instance listening on the specified port.
	Both IPv4 and IPv6 interfaces are used, if possible.
	Always returns a server instance; in the event of a failure, the instance holds the error details. Use IsListening()
	to query success. */
	static cServerHandleImplPtr Listen(UInt16 a_Port, cNetwork::cListenCallbacksPtr a_ListenCallbacks);

	// cServerHandle overrides:
	virtual void Close(void) override;
	virtual bool IsListening(void) const override { return m_IsListening; }

  protected:
	/** The callbacks used to notify about incoming connections. */
	cNetwork::cListenCallbacksPtr m_ListenCallbacks;

	/** The LibEvent handle representing the main listening socket. */
	evconnlistener * m_ConnListener;

	/** The LibEvent handle representing the secondary listening socket (only when side-by-side listening is needed,
	 * such as WinXP). */
	evconnlistener * m_SecondaryConnListener;

	/** Set to true when the server is initialized successfully and is listening for incoming connections. */
	bool m_IsListening;

	/** Container for all currently active connections on this server. */
	cTCPLinkImplPtrs m_Connections;

	/** Mutex protecting m_Connections againt multithreaded access. */
	cCriticalSection m_CS;

	/** Contains the error code for the failure to listen. Only valid for non-listening instances. */
	int m_ErrorCode;

	/** Contains the error message for the failure to listen. Only valid for non-listening instances. */
	AString m_ErrorMsg;

	/** The SharedPtr to self, so that it can be passed to created links. */
	cServerHandleImplPtr m_SelfPtr;



	/** Creates a new instance with the specified callbacks.
	Initializes the internals, but doesn't start listening yet. */
	cServerHandleImpl(cNetwork::cListenCallbacksPtr a_ListenCallbacks);

	/** Starts listening on the specified port.
	Returns true if successful, false on failure. On failure, sets m_ErrorCode and m_ErrorMsg. */
	bool Listen(UInt16 a_Port);

	/** The callback called by LibEvent upon incoming connection. */
	static void Callback(
		evconnlistener * a_Listener,
		evutil_socket_t a_Socket,
		sockaddr * a_Addr,
		int a_Len,
		void * a_Self
	);

	/** Removes the specified link from m_Connections.
	Called by cTCPLinkImpl when the link is terminated. */
	void RemoveLink(const cTCPLinkImpl * a_Link);
};