1 /**
2 Copyright: Copyright (c) 2014-2016 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 
7 module netlib.baseserver;
8 
9 import std.range;
10 
11 import derelict.enet.enet;
12 
13 import netlib.connection;
14 import netlib.clientstorage;
15 
16 abstract class BaseServer : Connection
17 {
18 	ClientStorage clientStorage;
19 
20 	void start(ConnectionSettings settings, uint host, ushort port)
21 	{
22 		ENetAddress address;
23 		address.host = host;
24 		address.port = port;
25 		settings.address = &address;
26 
27 		super.start(settings);
28 	}
29 
30 	/// Disconnects all clients.
31 	void disconnectAll()
32 	{
33 		if (!isRunning) return;
34 		foreach(peer; clientStorage.clientPeers.byValue)
35 		{
36 			enet_peer_disconnect(peer, 0);
37 		}
38 	}
39 
40 	/// Sends packet to specified clients.
41 	void sendTo(R)(R clients, ubyte[] data, ubyte channel = 0)
42 		if ((isInputRange!R && is(ElementType!R : ClientId)) ||
43 			is(R : ClientId))
44 	{
45 		if (!isRunning) return;
46 		ENetPacket* packet = enet_packet_create(data.ptr, data.length,
47 				ENET_PACKET_FLAG_RELIABLE);
48 		sendTo(clients, packet, channel);
49 	}
50 
51 	/// ditto
52 	void sendTo(R, P)(R clients, auto ref const(P) packet, ubyte channel = 0)
53 		if (((isInputRange!R && is(ElementType!R : ClientId)) ||
54 			is(R : ClientId)) &&
55 			is(P == struct))
56 	{
57 		sendTo(clients, createPacket(packet), channel);
58 	}
59 
60 	/// ditto
61 	void sendTo(R)(R clients, ENetPacket* packet, ubyte channel = 0)
62 		if ((isInputRange!R && is(ElementType!R : ClientId)) ||
63 			is(R : ClientId))
64 	{
65 		if (!isRunning) return;
66 		static if (isInputRange!R)
67 		{
68 			foreach(clientId; clients)
69 			{
70 				if (auto peer = clientStorage[clientId])
71 					enet_peer_send(peer, channel, packet);
72 			}
73 		}
74 		else // single ClientId
75 		{
76 			if (auto peer = clientStorage[clients])
77 				enet_peer_send(peer, channel, packet);
78 		}
79 	}
80 
81 	/// Sends packet to all clients.
82 	void sendToAll(P)(auto ref P packet, ubyte channel = 0)
83 		if (is(P == struct))
84 	{
85 		sendToAll(createPacket(packet), channel);
86 	}
87 
88 	/// ditto
89 	void sendToAll(ubyte[] data, ubyte channel = 0)
90 	{
91 		if (!isRunning) return;
92 		ENetPacket* packet = enet_packet_create(data.ptr, data.length,
93 					ENET_PACKET_FLAG_RELIABLE);
94 		sendToAll(packet, channel);
95 	}
96 
97 	/// ditto
98 	void sendToAll(ENetPacket* packet, ubyte channel = 0)
99 	{
100 		if (!isRunning) return;
101 		enet_host_broadcast(host, channel, packet);
102 	}
103 
104 	/// Sends packet to all clients except one.
105 	void sendToAllExcept(P)(ClientId exceptClient, auto ref const(P) packet, ubyte channel = 0)
106 		if (is(P == struct))
107 	{
108 		sendToAllExcept(exceptClient, createPacket(packet), channel);
109 	}
110 
111 	/// ditto
112 	void sendToAllExcept(ClientId exceptClient, ubyte[] data, ubyte channel = 0)
113 	{
114 		if (!isRunning) return;
115 		ENetPacket* packet = enet_packet_create(data.ptr, data.length,
116 					ENET_PACKET_FLAG_RELIABLE);
117 		sendToAllExcept(exceptClient, packet, channel);
118 	}
119 
120 	/// ditto
121 	void sendToAllExcept(ClientId exceptClient, ENetPacket* packet, ubyte channel = 0)
122 	{
123 		if (!isRunning) return;
124 		foreach(clientId, peer; clientStorage.clientPeers)
125 		{
126 			if (clientId != exceptClient && peer)
127 				enet_peer_send(peer, channel, packet);
128 		}
129 	}
130 }