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/externalconsole2.xml 8 */ 9 /** 10 * Packets used during the authentication process and to exhange the initial server's 11 * informations. 12 */ 13 module sul.protocol.externalconsole2.login; 14 15 import std.bitmanip : write, peek; 16 static import std.conv; 17 import std.system : Endian; 18 import std.typetuple : TypeTuple; 19 import std.typecons : Tuple; 20 import std.uuid : UUID; 21 22 import sul.utils.buffer; 23 import sul.utils.var; 24 25 static import sul.protocol.externalconsole2.types; 26 27 static if(__traits(compiles, { import sul.metadata.externalconsole2; })) import sul.metadata.externalconsole2; 28 29 alias Packets = TypeTuple!(AuthCredentials, Auth, Welcome); 30 31 /** 32 * First packet sent by the server when the connection is successfully established. 33 * It contains informations about how the external console shall authenticate itself. 34 */ 35 class AuthCredentials : Buffer { 36 37 public enum ubyte ID = 0; 38 39 public enum bool CLIENTBOUND = true; 40 public enum bool SERVERBOUND = false; 41 42 public enum string[] FIELDS = ["protocol", "hash", "hashAlgorithm", "payload"]; 43 44 /** 45 * Protocol used by the server. If the client uses a different one it should close 46 * the connection without trying to perform authentication. 47 */ 48 public ubyte protocol; 49 50 /** 51 * Whether to perform hashing on the password or not. 52 */ 53 public bool hash; 54 55 /** 56 * Algorithm used by the server to hash the concatenation of the password and the payload. 57 * The value should be sent in lower case without any separation symbol (for example 58 * `md5` instead of `MD5`, `sha256` instead of `SHA-256`). 59 * See Auth.hash for more details. 60 */ 61 public string hashAlgorithm; 62 63 /** 64 * Payload to cancatenate to the password before hashing it, as described in the Auth.hash's 65 * field description. 66 */ 67 public ubyte[] payload; 68 69 public pure nothrow @safe @nogc this() {} 70 71 public pure nothrow @safe @nogc this(ubyte protocol, bool hash=bool.init, string hashAlgorithm=string.init, ubyte[] payload=(ubyte[]).init) { 72 this.protocol = protocol; 73 this.hash = hash; 74 this.hashAlgorithm = hashAlgorithm; 75 this.payload = payload; 76 } 77 78 public pure nothrow @safe ubyte[] encode(bool writeId=true)() { 79 _buffer.length = 0; 80 static if(writeId){ writeBigEndianUbyte(ID); } 81 writeBigEndianUbyte(protocol); 82 writeBigEndianBool(hash); 83 if(hash==true){ writeBigEndianUshort(cast(ushort)hashAlgorithm.length); writeString(hashAlgorithm); } 84 if(hash==true){ writeBigEndianUshort(cast(ushort)payload.length); writeBytes(payload); } 85 return _buffer; 86 } 87 88 public pure nothrow @safe void decode(bool readId=true)() { 89 static if(readId){ ubyte _id; _id=readBigEndianUbyte(); } 90 protocol=readBigEndianUbyte(); 91 hash=readBigEndianBool(); 92 if(hash==true){ ushort afafz9ar=readBigEndianUshort(); hashAlgorithm=readString(afafz9ar); } 93 if(hash==true){ payload.length=readBigEndianUshort(); if(_buffer.length>=_index+payload.length){ payload=_buffer[_index.._index+payload.length].dup; _index+=payload.length; } } 94 } 95 96 public static pure nothrow @safe AuthCredentials fromBuffer(bool readId=true)(ubyte[] buffer) { 97 AuthCredentials ret = new AuthCredentials(); 98 ret._buffer = buffer; 99 ret.decode!readId(); 100 return ret; 101 } 102 103 public override string toString() { 104 return "AuthCredentials(protocol: " ~ std.conv.to!string(this.protocol) ~ ", hash: " ~ std.conv.to!string(this.hash) ~ ", hashAlgorithm: " ~ std.conv.to!string(this.hashAlgorithm) ~ ", payload: " ~ std.conv.to!string(this.payload) ~ ")"; 105 } 106 107 } 108 109 /** 110 * Performs authentication following the instruncions given by the AuthCredentials 111 * packet. 112 */ 113 class Auth : Buffer { 114 115 public enum ubyte ID = 1; 116 117 public enum bool CLIENTBOUND = false; 118 public enum bool SERVERBOUND = true; 119 120 public enum string[] FIELDS = ["hash"]; 121 122 /** 123 * Pasword encoded as UTF-8 if AuthCredentials.hash is `false` or the hash (specified 124 * in AuthCredentials.hashAlgorithm) of the password encoded as UTF-8 concatenated 125 * with the bytes from AuthCredentials.payload if `true`. 126 * The hash can be done with a function (if hashAlgorithm is `sha1`) in D: 127 * --- 128 * sha1Of(cast(ubyte[])password ~ authCredentials.payload); 129 * --- 130 * Or using `MessageDigest` in Java: 131 * --- 132 * MessageDigest md = MessageDigest.getInstance(authCredentials.hashAlgorithm); 133 * md.update(password.getBytes(StandardCharsets.UTF_8)); 134 * md.update(authCredentials.payload); 135 * byte[] hash = md.digest(); 136 * --- 137 */ 138 public ubyte[] hash; 139 140 public pure nothrow @safe @nogc this() {} 141 142 public pure nothrow @safe @nogc this(ubyte[] hash) { 143 this.hash = hash; 144 } 145 146 public pure nothrow @safe ubyte[] encode(bool writeId=true)() { 147 _buffer.length = 0; 148 static if(writeId){ writeBigEndianUbyte(ID); } 149 writeBigEndianUshort(cast(ushort)hash.length); writeBytes(hash); 150 return _buffer; 151 } 152 153 public pure nothrow @safe void decode(bool readId=true)() { 154 static if(readId){ ubyte _id; _id=readBigEndianUbyte(); } 155 hash.length=readBigEndianUshort(); if(_buffer.length>=_index+hash.length){ hash=_buffer[_index.._index+hash.length].dup; _index+=hash.length; } 156 } 157 158 public static pure nothrow @safe Auth fromBuffer(bool readId=true)(ubyte[] buffer) { 159 Auth ret = new Auth(); 160 ret._buffer = buffer; 161 ret.decode!readId(); 162 return ret; 163 } 164 165 public override string toString() { 166 return "Auth(hash: " ~ std.conv.to!string(this.hash) ~ ")"; 167 } 168 169 } 170 171 /** 172 * Indicates the status of the authentication process. 173 */ 174 class Welcome : Buffer { 175 176 public enum ubyte ID = 2; 177 178 public enum bool CLIENTBOUND = true; 179 public enum bool SERVERBOUND = false; 180 181 public enum string[] FIELDS = ["status"]; 182 183 public ubyte status; 184 185 public pure nothrow @safe @nogc this() {} 186 187 public pure nothrow @safe @nogc this(ubyte status) { 188 this.status = status; 189 } 190 191 public pure nothrow @safe ubyte[] encode(bool writeId=true)() { 192 _buffer.length = 0; 193 static if(writeId){ writeBigEndianUbyte(ID); } 194 writeBigEndianUbyte(status); 195 return _buffer; 196 } 197 198 public pure nothrow @safe void decode(bool readId=true)() { 199 static if(readId){ ubyte _id; _id=readBigEndianUbyte(); } 200 status=readBigEndianUbyte(); 201 } 202 203 public static pure nothrow @safe Welcome fromBuffer(bool readId=true)(ubyte[] buffer) { 204 Welcome ret = new Welcome(); 205 ret._buffer = buffer; 206 ret.decode!readId(); 207 return ret; 208 } 209 210 public override string toString() { 211 return "Welcome(status: " ~ std.conv.to!string(this.status) ~ ")"; 212 } 213 214 alias _encode = encode; 215 216 enum string variantField = "status"; 217 218 alias Variants = TypeTuple!(Accepted, WrongHash, TimedOut); 219 220 /** 221 * Sent when the hash sent in Auth matches the server's. 222 */ 223 public class Accepted { 224 225 public enum typeof(status) STATUS = 0; 226 227 public enum string[] FIELDS = ["remoteCommands", "software", "versions", "displayName", "games", "connectedNodes"]; 228 229 /** 230 * Indicates whether the external console can execute command remotely through the 231 * Command packet. 232 */ 233 public bool remoteCommands; 234 235 /** 236 * The server's software as a formatted string (without the version). 237 */ 238 public string software; 239 240 /** 241 * Versions of the server in a 3-btyes array readed as `[major, minor, release]`. 242 */ 243 public ubyte[3] versions; 244 245 /** 246 * Name of the server (not the game's MOTD!). It shouldn't contain Minecraft formatting 247 * codes. 248 */ 249 public string displayName; 250 251 /** 252 * Informations about the games and their protocols supported by the server. 253 */ 254 public sul.protocol.externalconsole2.types.Game[] games; 255 256 /** 257 * List of names of the nodes connected to the server, if it uses the hub-node layout, 258 * or an empty list. 259 */ 260 public string[] connectedNodes; 261 262 public pure nothrow @safe @nogc this() {} 263 264 public pure nothrow @safe @nogc this(bool remoteCommands, string software=string.init, ubyte[3] versions=(ubyte[3]).init, string displayName=string.init, sul.protocol.externalconsole2.types.Game[] games=(sul.protocol.externalconsole2.types.Game[]).init, string[] connectedNodes=(string[]).init) { 265 this.remoteCommands = remoteCommands; 266 this.software = software; 267 this.versions = versions; 268 this.displayName = displayName; 269 this.games = games; 270 this.connectedNodes = connectedNodes; 271 } 272 273 public pure nothrow @safe ubyte[] encode(bool writeId=true)() { 274 status = 0; 275 _encode!writeId(); 276 writeBigEndianBool(remoteCommands); 277 writeBigEndianUshort(cast(ushort)software.length); writeString(software); 278 writeBytes(versions); 279 writeBigEndianUshort(cast(ushort)displayName.length); writeString(displayName); 280 writeBigEndianUshort(cast(ushort)games.length); foreach(zfzm;games){ zfzm.encode(bufferInstance); } 281 writeBigEndianUshort(cast(ushort)connectedNodes.length); foreach(y9bvdvt9;connectedNodes){ writeBigEndianUshort(cast(ushort)y9bvdvt9.length); writeString(y9bvdvt9); } 282 return _buffer; 283 } 284 285 public pure nothrow @safe void decode() { 286 remoteCommands=readBigEndianBool(); 287 ushort c9ddcu=readBigEndianUshort(); software=readString(c9ddcu); 288 if(_buffer.length>=_index+versions.length){ versions=_buffer[_index.._index+versions.length].dup; _index+=versions.length; } 289 ushort zlcxe5bu=readBigEndianUshort(); displayName=readString(zlcxe5bu); 290 games.length=readBigEndianUshort(); foreach(ref zfzm;games){ zfzm.decode(bufferInstance); } 291 connectedNodes.length=readBigEndianUshort(); foreach(ref y9bvdvt9;connectedNodes){ ushort eldrdk=readBigEndianUshort(); y9bvdvt9=readString(eldrdk); } 292 } 293 294 public override string toString() { 295 return "Welcome.Accepted(remoteCommands: " ~ std.conv.to!string(this.remoteCommands) ~ ", software: " ~ std.conv.to!string(this.software) ~ ", versions: " ~ std.conv.to!string(this.versions) ~ ", displayName: " ~ std.conv.to!string(this.displayName) ~ ", games: " ~ std.conv.to!string(this.games) ~ ", connectedNodes: " ~ std.conv.to!string(this.connectedNodes) ~ ")"; 296 } 297 298 } 299 300 /** 301 * Sent when Auth is received but the given password or hash doesn't match the server's 302 * one. 303 */ 304 public class WrongHash { 305 306 public enum typeof(status) STATUS = 1; 307 308 public enum string[] FIELDS = []; 309 310 public pure nothrow @safe ubyte[] encode(bool writeId=true)() { 311 status = 1; 312 _encode!writeId(); 313 return _buffer; 314 } 315 316 public pure nothrow @safe void decode() { 317 } 318 319 public override string toString() { 320 return "Welcome.WrongHash()"; 321 } 322 323 } 324 325 /** 326 * Sent when Auth is not received and the server decides to close the connection because 327 * too much time has elapsed since the creation of the socket. 328 */ 329 public class TimedOut { 330 331 public enum typeof(status) STATUS = 2; 332 333 public enum string[] FIELDS = []; 334 335 public pure nothrow @safe ubyte[] encode(bool writeId=true)() { 336 status = 2; 337 _encode!writeId(); 338 return _buffer; 339 } 340 341 public pure nothrow @safe void decode() { 342 } 343 344 public override string toString() { 345 return "Welcome.TimedOut()"; 346 } 347 348 } 349 350 } 351