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