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/hncom1.xml
8  */
9 /**
10  * Packets used during the authentication process to exchange informations.
11  */
12 module sul.protocol.hncom1.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.hncom1.types;
25 
26 static if(__traits(compiles, { import sul.metadata.hncom1; })) import sul.metadata.hncom1;
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 = 1;
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 = 2;
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 = 3;
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", "onlineMode", "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 	 * Indicates whether the player are authenticated using the games' official authentication
214 	 * services and their identity should be trusted.
215 	 */
216 	public bool onlineMode;
217 
218 	/**
219 	 * Informations about the games supported by the hub.
220 	 */
221 	public sul.protocol.hncom1.types.GameInfo[] gamesInfo;
222 
223 	/**
224 	 * Number of players currently online and connected to other nodes.
225 	 */
226 	public uint online;
227 
228 	/**
229 	 * Number of maximum players that can connect to the server (that is the sum of the
230 	 * max players of the nodes already connected). The number may change after this node
231 	 * connects.
232 	 */
233 	public int max;
234 
235 	/**
236 	 * Default server's language in format (language_COUNTRY, e.g. en_GB) and also the
237 	 * default language for players that don't specify their language or for the ones which
238 	 * language is not supported by the server.
239 	 */
240 	public string language;
241 
242 	/**
243 	 * Languages accepted by the server in the same format as language. The list should
244 	 * always contain at least one element (the default language).
245 	 */
246 	public string[] acceptedLanguages;
247 
248 	/**
249 	 * Optional informations about the server's software, social accounts, system and options
250 	 * in the format indicated below.
251 	 * ---
252 	 * {
253 	 *    "software": {
254 	 *       "name": "SEL",
255 	 *       "version": "1.0.4",
256 	 *       "stable": true
257 	 *    },
258 	 *    "minecraft": {
259 	 *       "edu": false,
260 	 *       "realm": true
261 	 *    },
262 	 *    "social": {
263 	 *       "website": "example.com",
264 	 *       "facebook": "example-official",
265 	 *       "twitter": "example_tweets",
266 	 *       "youtube": "examplechannel",
267 	 *       "instagram": "example",
268 	 *       "google_plus": "example-plus"
269 	 *    },
270 	 *    "system": {
271 	 *       "os": "Ubuntu 16.04",
272 	 *       "cpu": "Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz",
273 	 *       "cores": 2,
274 	 *       "ram": 2147483648
275 	 *    }
276 	 * }
277 	 * ---
278 	 */
279 	public string additionalJson;
280 
281 	public pure nothrow @safe @nogc this() {}
282 
283 	public pure nothrow @safe @nogc this(ulong time, ulong serverId=ulong.init, ulong reservedUuids=ulong.init, string displayName=string.init, bool onlineMode=bool.init, sul.protocol.hncom1.types.GameInfo[] gamesInfo=(sul.protocol.hncom1.types.GameInfo[]).init, uint online=uint.init, int max=int.init, string language=string.init, string[] acceptedLanguages=(string[]).init, string additionalJson=string.init) {
284 		this.time = time;
285 		this.serverId = serverId;
286 		this.reservedUuids = reservedUuids;
287 		this.displayName = displayName;
288 		this.onlineMode = onlineMode;
289 		this.gamesInfo = gamesInfo;
290 		this.online = online;
291 		this.max = max;
292 		this.language = language;
293 		this.acceptedLanguages = acceptedLanguages;
294 		this.additionalJson = additionalJson;
295 	}
296 
297 	public pure nothrow @safe ubyte[] encode(bool writeId=true)() {
298 		_buffer.length = 0;
299 		static if(writeId){ writeBigEndianUbyte(ID); }
300 		writeBytes(varulong.encode(time));
301 		writeBytes(varulong.encode(serverId));
302 		writeBytes(varulong.encode(reservedUuids));
303 		writeBytes(varuint.encode(cast(uint)displayName.length)); writeString(displayName);
304 		writeBigEndianBool(onlineMode);
305 		writeBytes(varuint.encode(cast(uint)gamesInfo.length)); foreach(zfznbz;gamesInfo){ zfznbz.encode(bufferInstance); }
306 		writeBytes(varuint.encode(online));
307 		writeBytes(varint.encode(max));
308 		writeBytes(varuint.encode(cast(uint)language.length)); writeString(language);
309 		writeBytes(varuint.encode(cast(uint)acceptedLanguages.length)); foreach(ynzbzry5;acceptedLanguages){ writeBytes(varuint.encode(cast(uint)ynzbzry5.length)); writeString(ynzbzry5); }
310 		writeBytes(varuint.encode(cast(uint)additionalJson.length)); writeString(additionalJson);
311 		return _buffer;
312 	}
313 
314 	public pure nothrow @safe void decode(bool readId=true)() {
315 		static if(readId){ ubyte _id; _id=readBigEndianUbyte(); }
316 		time=varulong.decode(_buffer, &_index);
317 		serverId=varulong.decode(_buffer, &_index);
318 		reservedUuids=varulong.decode(_buffer, &_index);
319 		uint zlcxe5bu=varuint.decode(_buffer, &_index); displayName=readString(zlcxe5bu);
320 		onlineMode=readBigEndianBool();
321 		gamesInfo.length=varuint.decode(_buffer, &_index); foreach(ref zfznbz;gamesInfo){ zfznbz.decode(bufferInstance); }
322 		online=varuint.decode(_buffer, &_index);
323 		max=varint.decode(_buffer, &_index);
324 		uint bfzvzu=varuint.decode(_buffer, &_index); language=readString(bfzvzu);
325 		acceptedLanguages.length=varuint.decode(_buffer, &_index); foreach(ref ynzbzry5;acceptedLanguages){ uint e5ypeu=varuint.decode(_buffer, &_index); ynzbzry5=readString(e5ypeu); }
326 		uint yrarb5bp=varuint.decode(_buffer, &_index); additionalJson=readString(yrarb5bp);
327 	}
328 
329 	public static pure nothrow @safe HubInfo fromBuffer(bool readId=true)(ubyte[] buffer) {
330 		HubInfo ret = new HubInfo();
331 		ret._buffer = buffer;
332 		ret.decode!readId();
333 		return ret;
334 	}
335 
336 	public override string toString() {
337 		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) ~ ", onlineMode: " ~ std.conv.to!string(this.onlineMode) ~ ", 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) ~ ")";
338 	}
339 
340 }
341 
342 /**
343  * Informations about the node.
344  */
345 class NodeInfo : Buffer {
346 
347 	public enum ubyte ID = 4;
348 
349 	public enum bool CLIENTBOUND = false;
350 	public enum bool SERVERBOUND = true;
351 
352 	// max
353 	public enum uint UNLIMITED = 0;
354 
355 	public enum string[] FIELDS = ["time", "max", "acceptedGames", "plugins", "additionalJson"];
356 
357 	/**
358 	 * Unix time with microseconds precision that indicates the exact moment when this
359 	 * packet was created. It's used by the hub to calculate the latency.
360 	 */
361 	public ulong time;
362 
363 	/**
364 	 * Maximum number of players accepted by node.
365 	 */
366 	public uint max;
367 
368 	/**
369 	 * Informations about the games accepted by the node. There should be at least one
370 	 * combination of game/protocol that is also accepted by hub as indicated in HubInfo.gamesInfo,
371 	 * otherwise the node will never receive any player.
372 	 */
373 	public sul.protocol.hncom1.types.Game[] acceptedGames;
374 
375 	/**
376 	 * List of plugins loaded on the node for creating queries on the hub.
377 	 */
378 	public sul.protocol.hncom1.types.Plugin[] plugins;
379 
380 	/**
381 	 * Optional informations about the server's software and system, similar to HubInfo.additionalJson.
382 	 * ---
383 	 * {
384 	 *    "software": {
385 	 *       "name": "SEL",
386 	 *       "version": "1.0.4",
387 	 *       "stable": true
388 	 *    },
389 	 *    "system": {
390 	 *       "os": "Windows 10",
391 	 *       "cpu": "Intel(R) Core(TM) i7-5700U CPU @ 3.40GHz",
392 	 *       "cores": 4,
393 	 *       "ram": 8589934592
394 	 *    }
395 	 * }
396 	 * ---
397 	 */
398 	public string additionalJson;
399 
400 	public pure nothrow @safe @nogc this() {}
401 
402 	public pure nothrow @safe @nogc this(ulong time, uint max=uint.init, sul.protocol.hncom1.types.Game[] acceptedGames=(sul.protocol.hncom1.types.Game[]).init, sul.protocol.hncom1.types.Plugin[] plugins=(sul.protocol.hncom1.types.Plugin[]).init, string additionalJson=string.init) {
403 		this.time = time;
404 		this.max = max;
405 		this.acceptedGames = acceptedGames;
406 		this.plugins = plugins;
407 		this.additionalJson = additionalJson;
408 	}
409 
410 	public pure nothrow @safe ubyte[] encode(bool writeId=true)() {
411 		_buffer.length = 0;
412 		static if(writeId){ writeBigEndianUbyte(ID); }
413 		writeBytes(varulong.encode(time));
414 		writeBytes(varuint.encode(max));
415 		writeBytes(varuint.encode(cast(uint)acceptedGames.length)); foreach(ynzbzry1;acceptedGames){ ynzbzry1.encode(bufferInstance); }
416 		writeBytes(varuint.encode(cast(uint)plugins.length)); foreach(cxzlc;plugins){ cxzlc.encode(bufferInstance); }
417 		writeBytes(varuint.encode(cast(uint)additionalJson.length)); writeString(additionalJson);
418 		return _buffer;
419 	}
420 
421 	public pure nothrow @safe void decode(bool readId=true)() {
422 		static if(readId){ ubyte _id; _id=readBigEndianUbyte(); }
423 		time=varulong.decode(_buffer, &_index);
424 		max=varuint.decode(_buffer, &_index);
425 		acceptedGames.length=varuint.decode(_buffer, &_index); foreach(ref ynzbzry1;acceptedGames){ ynzbzry1.decode(bufferInstance); }
426 		plugins.length=varuint.decode(_buffer, &_index); foreach(ref cxzlc;plugins){ cxzlc.decode(bufferInstance); }
427 		uint yrarb5bp=varuint.decode(_buffer, &_index); additionalJson=readString(yrarb5bp);
428 	}
429 
430 	public static pure nothrow @safe NodeInfo fromBuffer(bool readId=true)(ubyte[] buffer) {
431 		NodeInfo ret = new NodeInfo();
432 		ret._buffer = buffer;
433 		ret.decode!readId();
434 		return ret;
435 	}
436 
437 	public override string toString() {
438 		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) ~ ")";
439 	}
440 
441 }
442