1 /* 2 * Copyright (c) 2017 SEL 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * See the GNU Lesser General Public License for more details. 13 * 14 */ 15 module sel.hncom.login; 16 17 import std.json : JSONValue; 18 import std.typecons : Tuple; 19 20 import sel.hncom.about; 21 import sel.hncom.io : IO; 22 23 /** 24 * First packet sent by the client after the connection is established. 25 * It contains informations used by the hub to check permissions and compatibility. 26 */ 27 @serverbound struct ConnectionRequest { 28 29 enum ubyte ID = 1; 30 31 /** 32 * Password, if the hub requires one, or an empty string. 33 */ 34 string password; 35 36 /** 37 * Name of the node that will be validated by the hub. It should always be 38 * lowercase and only contain letters, numbers, dashes and underscores. 39 */ 40 string name; 41 42 /** 43 * Indicates whether the node accepts clients when they first connect to the 44 * hub or exclusively when they are transferred. 45 */ 46 bool main = true; 47 48 /** 49 * Version of the protocol used by the client that must match the hub's one. 50 */ 51 uint protocol = __PROTOCOL__; 52 53 mixin IO!(password, name, main, protocol); 54 55 } 56 57 /** 58 * Reply to ConnectionRequest sent only when the node's ip is accepted by the hub. 59 * It contains the connection status (accepted or an error code) and the hub's protocol. 60 */ 61 @clientbound struct ConnectionResponse { 62 63 enum ubyte ID = 2; 64 65 enum : ubyte { 66 67 OK, 68 OUTDATED_HUB, /// The hub uses an old version of hncom 69 OUTDATED_NODE, /// The node uses an old version of hncom 70 PASSWORD_REQUIRED, /// A password is required to connect 71 WRONG_PASSWORD, /// The password doesn't match the hub's one 72 INVALID_NAME_LENGTH, /// The name is too short or too long 73 INVALID_NAME_CHARACTERS, /// The name contains invalid characters 74 NAME_ALREADY_USED, /// There's already a node connected with the same name 75 NAME_RESERVED, /// The name cannot be used because the hub has reserved it for something else 76 BLOCKED_BY_PLUGIN, /// A plugin has blocked the node from connecting 77 78 } 79 80 /** 81 * Indicates the status of connection. If not 0, it indicates an error. 82 */ 83 ubyte status; 84 85 /** 86 * Indicates the version of the protocol used by the hub when the status 87 * code indicates that the hub or the node is obsolete. 88 */ 89 uint protocol = __PROTOCOL__; 90 91 mixin IO!(status, protocol); 92 93 } 94 95 /** 96 * Hub's informations. 97 */ 98 @clientbound struct HubInfo { 99 100 enum ubyte ID = 3; 101 102 enum int UNLIMITED = -1; 103 104 alias GameInfo = Tuple!(string, "motd", uint[], "protocols", bool, "onlineMode", ushort, "port"); 105 106 /** 107 * Server's id, either given by a snoop system or randomly generated at runtime. 108 */ 109 ulong serverId; 110 111 /** 112 * First number of the 4,294,967,296 (2^32) reserved by the hub to create the node's UUIDs. 113 * Every UUID generated by the node is formed by the server's id (most signicant) 114 * and the next reserved uuid (least significant). This way every UUID in the hub 115 * and in the connected nodes is always different. 116 */ 117 ulong reservedUUIDs; 118 119 /** 120 * Unformatted name of the server as indicated in the hub's configuration file. 121 */ 122 string displayName; 123 124 /** 125 * Informations about the games supported by the hub. 126 */ 127 GameInfo[ubyte] gamesInfo; 128 129 /** 130 * Number of players currently online and connected to other nodes. 131 */ 132 uint online; 133 134 /** 135 * Number of maximum players that can connect to the server (that is the sum 136 * of the max players of the nodes already connected). 137 * The number may change after the current node connects. 138 */ 139 int max; 140 141 /** 142 * Default server's language in format (language_COUNTRY, e.g. en_GB) and also the 143 * default language for players that don't specify their language or for the ones 144 * which language is not supported by the server. 145 */ 146 string language; 147 148 /** 149 * Languages accepted by the server in the same format as language. 150 * The list should always contain at least one element (the default language). 151 */ 152 string[] acceptedLanguages; 153 154 /** 155 * Optional informations about the server's software, social accounts, system and options. 156 * Example: 157 * --- 158 * { 159 * "software": { 160 * "name": "selery", 161 * "version": "0.0.1", 162 * "stable": true 163 * }, 164 * "minecraft": { 165 * "edu": false, 166 * "realm": true 167 * }, 168 * "social": { 169 * "website": "example.com", 170 * "facebook": "example-official", 171 * "twitter": "example_tweets", 172 * "youtube": "examplechannel", 173 * "instagram": "example", 174 * "google-plus": "example-plus" 175 * }, 176 * "system": { 177 * "os": "Ubuntu 16.04", 178 * "cpu": "Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz", 179 * "cores": 2, 180 * "ram": 2147483648 181 * } 182 * } 183 * --- 184 */ 185 JSONValue additionalJSON; 186 187 mixin IO!(serverId, reservedUUIDs, displayName, gamesInfo, online, max, language, acceptedLanguages, additionalJSON); 188 189 } 190 191 /** 192 * Node's informations. 193 */ 194 @serverbound struct NodeInfo { 195 196 enum ubyte ID = 4; 197 198 enum uint UNLIMITED = 0; 199 200 alias Plugin = Tuple!(string, "name", string, "version_"); 201 202 /** 203 * Informations about the games accepted by the node. There should be at least 204 * one combination of game/protocols that is also accepted by hub as indicated 205 * in HubInfo.gamesInfo, otherwise the node will never receive any player. 206 */ 207 uint[][ubyte] acceptedGames; 208 209 /** 210 * Maximum number of players accepted by node. 211 */ 212 uint max; 213 214 /** 215 * List of plugins loaded on the node for creating queries on the hub. 216 */ 217 Plugin[] plugins; 218 219 /** 220 * Optional informations about the server's software and system, 221 * similar to HubInfo's additionalJson field. 222 * Example: 223 * --- 224 * { 225 * "software": { 226 * "name": "selery", 227 * "version": "0.0.1", 228 * "stable": true 229 * }, 230 * "system": { 231 * "os": "Windows 10", 232 * "cpu": "Intel(R) Core(TM) i7-5700U CPU @ 3.40GHz", 233 * "cores": 4, 234 * "ram": 8589934592 235 * } 236 * } 237 * --- 238 */ 239 JSONValue additionalJSON; 240 241 mixin IO!(acceptedGames, max, plugins, additionalJSON); 242 243 }