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