1 /*
2  * This file was automatically generated by sel-utils and
3  * released under the MIT License.
4  * 
5  * License: https://github.com/sel-project/sel-utils/blob/master/LICENSE
6  * Repository: https://github.com/sel-project/sel-utils
7  * Generated from https://github.com/sel-project/sel-utils/blob/master/xml/protocol/hncom2.xml
8  */
9 /**
10  * Packets used during the authentication process to exchange informations.
11  */
12 module sul.protocol.hncom2.login;
13 
14 import std.bitmanip : write, peek;
15 static import std.conv;
16 import std.system : Endian;
17 import std.typetuple : TypeTuple;
18 import std.typecons : Tuple;
19 import std.uuid : UUID;
20 
21 import sul.utils.buffer;
22 import sul.utils.var;
23 
24 static import sul.protocol.hncom2.types;
25 
26 static if(__traits(compiles, { import sul.metadata.hncom2; })) import sul.metadata.hncom2;
27 
28 alias Packets = TypeTuple!(ConnectionRequest, ConnectionResponse, HubInfo, NodeInfo);
29 
30 /**
31  * First real packet sent by the client with its informations.
32  */
33 class ConnectionRequest : Buffer {
34 
35 	public enum ubyte ID = 3;
36 
37 	public enum bool CLIENTBOUND = false;
38 	public enum bool SERVERBOUND = true;
39 
40 	public enum string[] FIELDS = ["protocol", "password", "name", "main"];
41 
42 	/**
43 	 * Version of the protocol used by the client that must match the hub's one.
44 	 */
45 	public uint protocol;
46 
47 	/**
48 	 * Password, if the hub requires one, or an empty string.
49 	 */
50 	public string password;
51 
52 	/**
53 	 * Name of the node that will be validated by the hub. It should always be lowercase
54 	 * and only contain letters, numbers, dashes and underscores.
55 	 */
56 	public string name;
57 
58 	/**
59 	 * Indicates whether the node accepts clients when they first connect to the hub or
60 	 * exclusively when they are manually transferred.
61 	 */
62 	public bool main = true;
63 
64 	public pure nothrow @safe @nogc this() {}
65 
66 	public pure nothrow @safe @nogc this(uint protocol, string password=string.init, string name=string.init, bool main=true) {
67 		this.protocol = protocol;
68 		this.password = password;
69 		this.name = name;
70 		this.main = main;
71 	}
72 
73 	public pure nothrow @safe ubyte[] encode(bool writeId=true)() {
74 		_buffer.length = 0;
75 		static if(writeId){ writeBigEndianUbyte(ID); }
76 		writeBytes(varuint.encode(protocol));
77 		writeBytes(varuint.encode(cast(uint)password.length)); writeString(password);
78 		writeBytes(varuint.encode(cast(uint)name.length)); writeString(name);
79 		writeBigEndianBool(main);
80 		return _buffer;
81 	}
82 
83 	public pure nothrow @safe void decode(bool readId=true)() {
84 		static if(readId){ ubyte _id; _id=readBigEndianUbyte(); }
85 		protocol=varuint.decode(_buffer, &_index);
86 		uint cfcdcq=varuint.decode(_buffer, &_index); password=readString(cfcdcq);
87 		uint bfz=varuint.decode(_buffer, &_index); name=readString(bfz);
88 		main=readBigEndianBool();
89 	}
90 
91 	public static pure nothrow @safe ConnectionRequest fromBuffer(bool readId=true)(ubyte[] buffer) {
92 		ConnectionRequest ret = new ConnectionRequest();
93 		ret._buffer = buffer;
94 		ret.decode!readId();
95 		return ret;
96 	}
97 
98 	public override string toString() {
99 		return "ConnectionRequest(protocol: " ~ std.conv.to!string(this.protocol) ~ ", password: " ~ std.conv.to!string(this.password) ~ ", name: " ~ std.conv.to!string(this.name) ~ ", main: " ~ std.conv.to!string(this.main) ~ ")";
100 	}
101 
102 }
103 
104 /**
105  * Reply sent after the ConnectionRequest packet if the node's ip has been accepted.
106  * It indicates the status of the connection.
107  */
108 class ConnectionResponse : Buffer {
109 
110 	public enum ubyte ID = 4;
111 
112 	public enum bool CLIENTBOUND = true;
113 	public enum bool SERVERBOUND = false;
114 
115 	// status
116 	public enum ubyte OK = 0;
117 	public enum ubyte OUTDATED_HUB = 1;
118 	public enum ubyte OUTDATED_NODE = 2;
119 	public enum ubyte PASSWORD_REQUIRED = 3;
120 	public enum ubyte WRONG_PASSWORD = 4;
121 	public enum ubyte INVALID_NAME_LENGTH = 5;
122 	public enum ubyte INVALID_NAME_CHARACTERS = 6;
123 	public enum ubyte NAME_ALREADY_USED = 7;
124 	public enum ubyte NAME_RESERVED = 8;
125 
126 	public enum string[] FIELDS = ["status", "protocol"];
127 
128 	/**
129 	 * Indicates the status of connection. If not 0, it indicates an error.
130 	 */
131 	public ubyte status;
132 
133 	/**
134 	 * Indicates the version of the protocol used by the hub when the status code indicates
135 	 * that the hub or the node is obsolete.
136 	 */
137 	public uint protocol;
138 
139 	public pure nothrow @safe @nogc this() {}
140 
141 	public pure nothrow @safe @nogc this(ubyte status, uint protocol=uint.init) {
142 		this.status = status;
143 		this.protocol = protocol;
144 	}
145 
146 	public pure nothrow @safe ubyte[] encode(bool writeId=true)() {
147 		_buffer.length = 0;
148 		static if(writeId){ writeBigEndianUbyte(ID); }
149 		writeBigEndianUbyte(status);
150 		if(status==1||status==2){ writeBytes(varuint.encode(protocol)); }
151 		return _buffer;
152 	}
153 
154 	public pure nothrow @safe void decode(bool readId=true)() {
155 		static if(readId){ ubyte _id; _id=readBigEndianUbyte(); }
156 		status=readBigEndianUbyte();
157 		if(status==1||status==2){ protocol=varuint.decode(_buffer, &_index); }
158 	}
159 
160 	public static pure nothrow @safe ConnectionResponse fromBuffer(bool readId=true)(ubyte[] buffer) {
161 		ConnectionResponse ret = new ConnectionResponse();
162 		ret._buffer = buffer;
163 		ret.decode!readId();
164 		return ret;
165 	}
166 
167 	public override string toString() {
168 		return "ConnectionResponse(status: " ~ std.conv.to!string(this.status) ~ ", protocol: " ~ std.conv.to!string(this.protocol) ~ ")";
169 	}
170 
171 }
172 
173 /**
174  * Informations about the hub.
175  */
176 class HubInfo : Buffer {
177 
178 	public enum ubyte ID = 5;
179 
180 	public enum bool CLIENTBOUND = true;
181 	public enum bool SERVERBOUND = false;
182 
183 	// max
184 	public enum int UNLIMITED = -1;
185 
186 	public enum string[] FIELDS = ["time", "serverId", "reservedUuids", "displayName", "gamesInfo", "online", "max", "language", "acceptedLanguages", "additionalJson"];
187 
188 	/**
189 	 * Unix time with microseconds precision that indicates the exact moment when this
190 	 * packet was created. It's used by the node to calculate the latency.
191 	 */
192 	public ulong time;
193 
194 	/**
195 	 * Server's id, either given by a snoop system or randomly generated at runtime.
196 	 */
197 	public ulong serverId;
198 
199 	/**
200 	 * First number of the 4,294,967,296 (2³²) reserved by the hub to create the node's
201 	 * UUIDs. Every UUID generated by the node is formed by the server's id (most signicant)
202 	 * and the next reserved uuid (least significant). This way every UUID in the hub and
203 	 * in the connected nodes is always different.
204 	 */
205 	public ulong reservedUuids;
206 
207 	/**
208 	 * Unformatted name of the server as indicated in the hub's configuration file.
209 	 */
210 	public string displayName;
211 
212 	/**
213 	 * Informations about the games supported by the hub.
214 	 */
215 	public sul.protocol.hncom2.types.GameInfo[] gamesInfo;
216 
217 	/**
218 	 * Number of players currently online and connected to other nodes.
219 	 */
220 	public uint online;
221 
222 	/**
223 	 * Number of maximum players that can connect to the server (that is the sum of the
224 	 * max players of the nodes already connected). The number may change after this node
225 	 * connects.
226 	 */
227 	public int max;
228 
229 	/**
230 	 * Default server's language in format (language_COUNTRY, e.g. en_GB) and also the
231 	 * default language for players that don't specify their language or for the ones which
232 	 * language is not supported by the server.
233 	 */
234 	public string language;
235 
236 	/**
237 	 * Languages accepted by the server in the same format as language. The list should
238 	 * always contain at least one element (the default language).
239 	 */
240 	public string[] acceptedLanguages;
241 
242 	/**
243 	 * Optional informations about the server's software, social accounts, system and options
244 	 * in the format indicated below.
245 	 * ---
246 	 * {
247 	 *    "software": {
248 	 *       "name": "SEL",
249 	 *       "version": "1.0.4",
250 	 *       "stable": true
251 	 *    },
252 	 *    "minecraft": {
253 	 *       "edu": false,
254 	 *       "realm": true
255 	 *    },
256 	 *    "social": {
257 	 *       "website": "example.com",
258 	 *       "facebook": "example-official",
259 	 *       "twitter": "example_tweets",
260 	 *       "youtube": "examplechannel",
261 	 *       "instagram": "example",
262 	 *       "google-plus": "example-plus"
263 	 *    },
264 	 *    "system": {
265 	 *       "os": "Ubuntu 16.04",
266 	 *       "cpu": "Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz",
267 	 *       "cores": 2,
268 	 *       "ram": 2147483648
269 	 *    }
270 	 * }
271 	 * ---
272 	 */
273 	public string additionalJson;
274 
275 	public pure nothrow @safe @nogc this() {}
276 
277 	public pure nothrow @safe @nogc this(ulong time, ulong serverId=ulong.init, ulong reservedUuids=ulong.init, string displayName=string.init, sul.protocol.hncom2.types.GameInfo[] gamesInfo=(sul.protocol.hncom2.types.GameInfo[]).init, uint online=uint.init, int max=int.init, string language=string.init, string[] acceptedLanguages=(string[]).init, string additionalJson=string.init) {
278 		this.time = time;
279 		this.serverId = serverId;
280 		this.reservedUuids = reservedUuids;
281 		this.displayName = displayName;
282 		this.gamesInfo = gamesInfo;
283 		this.online = online;
284 		this.max = max;
285 		this.language = language;
286 		this.acceptedLanguages = acceptedLanguages;
287 		this.additionalJson = additionalJson;
288 	}
289 
290 	public pure nothrow @safe ubyte[] encode(bool writeId=true)() {
291 		_buffer.length = 0;
292 		static if(writeId){ writeBigEndianUbyte(ID); }
293 		writeBytes(varulong.encode(time));
294 		writeBytes(varulong.encode(serverId));
295 		writeBytes(varulong.encode(reservedUuids));
296 		writeBytes(varuint.encode(cast(uint)displayName.length)); writeString(displayName);
297 		writeBytes(varuint.encode(cast(uint)gamesInfo.length)); foreach(zfznbz;gamesInfo){ zfznbz.encode(bufferInstance); }
298 		writeBytes(varuint.encode(online));
299 		writeBytes(varint.encode(max));
300 		writeBytes(varuint.encode(cast(uint)language.length)); writeString(language);
301 		writeBytes(varuint.encode(cast(uint)acceptedLanguages.length)); foreach(ynzbzry5;acceptedLanguages){ writeBytes(varuint.encode(cast(uint)ynzbzry5.length)); writeString(ynzbzry5); }
302 		writeBytes(varuint.encode(cast(uint)additionalJson.length)); writeString(additionalJson);
303 		return _buffer;
304 	}
305 
306 	public pure nothrow @safe void decode(bool readId=true)() {
307 		static if(readId){ ubyte _id; _id=readBigEndianUbyte(); }
308 		time=varulong.decode(_buffer, &_index);
309 		serverId=varulong.decode(_buffer, &_index);
310 		reservedUuids=varulong.decode(_buffer, &_index);
311 		uint zlcxe5bu=varuint.decode(_buffer, &_index); displayName=readString(zlcxe5bu);
312 		gamesInfo.length=varuint.decode(_buffer, &_index); foreach(ref zfznbz;gamesInfo){ zfznbz.decode(bufferInstance); }
313 		online=varuint.decode(_buffer, &_index);
314 		max=varint.decode(_buffer, &_index);
315 		uint bfzvzu=varuint.decode(_buffer, &_index); language=readString(bfzvzu);
316 		acceptedLanguages.length=varuint.decode(_buffer, &_index); foreach(ref ynzbzry5;acceptedLanguages){ uint e5ypeu=varuint.decode(_buffer, &_index); ynzbzry5=readString(e5ypeu); }
317 		uint yrarb5bp=varuint.decode(_buffer, &_index); additionalJson=readString(yrarb5bp);
318 	}
319 
320 	public static pure nothrow @safe HubInfo fromBuffer(bool readId=true)(ubyte[] buffer) {
321 		HubInfo ret = new HubInfo();
322 		ret._buffer = buffer;
323 		ret.decode!readId();
324 		return ret;
325 	}
326 
327 	public override string toString() {
328 		return "HubInfo(time: " ~ std.conv.to!string(this.time) ~ ", serverId: " ~ std.conv.to!string(this.serverId) ~ ", reservedUuids: " ~ std.conv.to!string(this.reservedUuids) ~ ", displayName: " ~ std.conv.to!string(this.displayName) ~ ", gamesInfo: " ~ std.conv.to!string(this.gamesInfo) ~ ", online: " ~ std.conv.to!string(this.online) ~ ", max: " ~ std.conv.to!string(this.max) ~ ", language: " ~ std.conv.to!string(this.language) ~ ", acceptedLanguages: " ~ std.conv.to!string(this.acceptedLanguages) ~ ", additionalJson: " ~ std.conv.to!string(this.additionalJson) ~ ")";
329 	}
330 
331 }
332 
333 /**
334  * Informations about the node.
335  */
336 class NodeInfo : Buffer {
337 
338 	public enum ubyte ID = 6;
339 
340 	public enum bool CLIENTBOUND = false;
341 	public enum bool SERVERBOUND = true;
342 
343 	// max
344 	public enum uint UNLIMITED = 0;
345 
346 	public enum string[] FIELDS = ["time", "max", "acceptedGames", "plugins", "additionalJson"];
347 
348 	/**
349 	 * Unix time with microseconds precision that indicates the exact moment when this
350 	 * packet was created. It's used by the hub to calculate the latency.
351 	 */
352 	public ulong time;
353 
354 	/**
355 	 * Maximum number of players accepted by node.
356 	 */
357 	public uint max;
358 
359 	/**
360 	 * Informations about the games accepted by the node. There should be at least one
361 	 * combination of game/protocol that is also accepted by hub as indicated in HubInfo.gamesInfo,
362 	 * otherwise the node will never receive any player.
363 	 */
364 	public sul.protocol.hncom2.types.Game[] acceptedGames;
365 
366 	/**
367 	 * List of plugins loaded on the node for creating queries on the hub.
368 	 */
369 	public sul.protocol.hncom2.types.Plugin[] plugins;
370 
371 	/**
372 	 * Optional informations about the server's software and system, similar to HubInfo.additionalJson.
373 	 * ---
374 	 * {
375 	 *    "software": {
376 	 *       "name": "SEL",
377 	 *       "version": "1.0.4",
378 	 *       "stable": true
379 	 *    },
380 	 *    "system": {
381 	 *       "os": "Windows 10",
382 	 *       "cpu": "Intel(R) Core(TM) i7-5700U CPU @ 3.40GHz",
383 	 *       "cores": 4,
384 	 *       "ram": 8589934592
385 	 *    }
386 	 * }
387 	 * ---
388 	 */
389 	public string additionalJson;
390 
391 	public pure nothrow @safe @nogc this() {}
392 
393 	public pure nothrow @safe @nogc this(ulong time, uint max=uint.init, sul.protocol.hncom2.types.Game[] acceptedGames=(sul.protocol.hncom2.types.Game[]).init, sul.protocol.hncom2.types.Plugin[] plugins=(sul.protocol.hncom2.types.Plugin[]).init, string additionalJson=string.init) {
394 		this.time = time;
395 		this.max = max;
396 		this.acceptedGames = acceptedGames;
397 		this.plugins = plugins;
398 		this.additionalJson = additionalJson;
399 	}
400 
401 	public pure nothrow @safe ubyte[] encode(bool writeId=true)() {
402 		_buffer.length = 0;
403 		static if(writeId){ writeBigEndianUbyte(ID); }
404 		writeBytes(varulong.encode(time));
405 		writeBytes(varuint.encode(max));
406 		writeBytes(varuint.encode(cast(uint)acceptedGames.length)); foreach(ynzbzry1;acceptedGames){ ynzbzry1.encode(bufferInstance); }
407 		writeBytes(varuint.encode(cast(uint)plugins.length)); foreach(cxzlc;plugins){ cxzlc.encode(bufferInstance); }
408 		writeBytes(varuint.encode(cast(uint)additionalJson.length)); writeString(additionalJson);
409 		return _buffer;
410 	}
411 
412 	public pure nothrow @safe void decode(bool readId=true)() {
413 		static if(readId){ ubyte _id; _id=readBigEndianUbyte(); }
414 		time=varulong.decode(_buffer, &_index);
415 		max=varuint.decode(_buffer, &_index);
416 		acceptedGames.length=varuint.decode(_buffer, &_index); foreach(ref ynzbzry1;acceptedGames){ ynzbzry1.decode(bufferInstance); }
417 		plugins.length=varuint.decode(_buffer, &_index); foreach(ref cxzlc;plugins){ cxzlc.decode(bufferInstance); }
418 		uint yrarb5bp=varuint.decode(_buffer, &_index); additionalJson=readString(yrarb5bp);
419 	}
420 
421 	public static pure nothrow @safe NodeInfo fromBuffer(bool readId=true)(ubyte[] buffer) {
422 		NodeInfo ret = new NodeInfo();
423 		ret._buffer = buffer;
424 		ret.decode!readId();
425 		return ret;
426 	}
427 
428 	public override string toString() {
429 		return "NodeInfo(time: " ~ std.conv.to!string(this.time) ~ ", max: " ~ std.conv.to!string(this.max) ~ ", acceptedGames: " ~ std.conv.to!string(this.acceptedGames) ~ ", plugins: " ~ std.conv.to!string(this.plugins) ~ ", additionalJson: " ~ std.conv.to!string(this.additionalJson) ~ ")";
430 	}
431 
432 }
433