1 /* 2 * Copyright (c) 2017-2018 sel-project 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in all 12 * copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 * 22 */ 23 /** 24 * Copyright: Copyright (c) 2017-2018 sel-project 25 * License: MIT 26 * Authors: Kripth 27 * Source: $(HTTP github.com/sel-project/sel-hncom/sel/hncom/login.d, sel/hncom/login.d) 28 */ 29 module sel.hncom.login; 30 31 import std.json : JSONValue; 32 import std.typecons : Tuple; 33 34 import sel.hncom.about; 35 import sel.hncom.io : IO; 36 37 /** 38 * First packet sent by the client after the connection is established. 39 * It contains informations used by the hub to check permissions and compatibility. 40 */ 41 @serverbound struct ConnectionRequest { 42 43 enum ubyte ID = 1; 44 45 /** 46 * Name of the node that will be validated by the hub. It should always be 47 * lowercase and only contain letters, numbers, dashes and underscores. 48 */ 49 string name; 50 51 /** 52 * Password, if the hub requires one, or an empty string. 53 */ 54 string password; 55 56 /** 57 * Indicates whether the node accepts clients when they first connect to the 58 * hub or exclusively when they are transferred. 59 */ 60 bool main = true; 61 62 /** 63 * Version of the protocol used by the client that must match the hub's one. 64 */ 65 uint protocol = __PROTOCOL__; 66 67 mixin IO!(password, name, main, protocol); 68 69 } 70 71 /** 72 * Reply to ConnectionRequest sent only when the node's ip is accepted by the hub. 73 * It contains the connection status (accepted or an error code) and the hub's protocol. 74 */ 75 @clientbound struct ConnectionResponse { 76 77 enum ubyte ID = 2; 78 79 enum : ubyte { 80 81 OK, 82 OUTDATED_HUB, /// The hub uses an old version of hncom 83 OUTDATED_NODE, /// The node uses an old version of hncom 84 PASSWORD_REQUIRED, /// A password is required to connect 85 WRONG_PASSWORD, /// The password doesn't match the hub's one 86 INVALID_NAME_LENGTH, /// The name is too short or too long 87 INVALID_NAME_CHARACTERS, /// The name contains invalid characters 88 NAME_ALREADY_USED, /// There's already a node connected with the same name 89 NAME_RESERVED, /// The name cannot be used because the hub has reserved it for something else 90 BLOCKED_BY_PLUGIN, /// A plugin has blocked the node from connecting 91 92 } 93 94 /** 95 * Indicates the status of connection. If not 0, it indicates an error. 96 */ 97 ubyte status; 98 99 /** 100 * Indicates the version of the protocol used by the hub when the status 101 * code indicates that the hub or the node is obsolete. 102 */ 103 uint protocol = __PROTOCOL__; 104 105 mixin IO!(status, protocol); 106 107 } 108 109 /** 110 * Hub's informations. 111 */ 112 @clientbound struct HubInfo { 113 114 enum ubyte ID = 3; 115 116 enum int UNLIMITED = -1; 117 118 alias GameInfo = Tuple!(string, "motd", uint[], "protocols", bool, "onlineMode", ushort, "port"); 119 120 /** 121 * Server's id, either given by a snoop system or randomly generated at runtime. 122 */ 123 ulong serverId; 124 125 /** 126 * First number of the 4,294,967,296 (2^32) reserved by the hub to create the node's UUIDs. 127 * Every UUID generated by the node is formed by the server's id (most signicant) 128 * and the next reserved uuid (least significant). This way every UUID in the hub 129 * and in the connected nodes is always different. 130 */ 131 ulong reservedUUIDs; 132 133 /** 134 * Unformatted name of the server as indicated in the hub's configuration file. 135 */ 136 string displayName; 137 138 /** 139 * Informations about the games supported by the hub. 140 */ 141 GameInfo[ubyte] gamesInfo; 142 143 /** 144 * Number of players currently online and connected to other nodes. 145 */ 146 uint online; 147 148 /** 149 * Number of maximum players that can connect to the server (that is the sum 150 * of the max players of the nodes already connected). 151 * The number may change after the current node connects. 152 */ 153 int max; 154 155 /** 156 * Languages accepted by the server in format ISO 639.1 (language code) underscore 157 * ISO 3166 (country code), e.g. en_US. 158 * The list must contain at least one element. 159 */ 160 string[] acceptedLanguages; 161 162 /** 163 * Indicates whether the web admin protocol is active on the hub. If it is the 164 * node should send the port where it will listen for connections in its info packet. 165 */ 166 bool webAdmin; 167 168 /** 169 * Optional informations about the server's software, social accounts, system and options. 170 * Example: 171 * --- 172 * { 173 * "software": { 174 * "name": "Selery", 175 * "version": "0.1.0", 176 * "stable": true 177 * }, 178 * "minecraft": { 179 * "edu": false, 180 * "realm": true 181 * }, 182 * "social": { 183 * "website": "example.com", 184 * "facebook": "example-official", 185 * "twitter": "example_tweets", 186 * "youtube": "examplechannel", 187 * "instagram": "example", 188 * "google-plus": "example-plus" 189 * }, 190 * "system": { 191 * "os": "Ubuntu 16.04", 192 * "cpu": "Intel(R) Core(TM) i5-5200U CPU @ 2.20GHz", 193 * "cores": 2, 194 * "ram": 2147483648 195 * } 196 * } 197 * --- 198 */ 199 JSONValue additionalJSON; 200 201 mixin IO!(serverId, reservedUUIDs, displayName, gamesInfo, online, max, acceptedLanguages, webAdmin, additionalJSON); 202 203 } 204 205 /** 206 * Node's informations. 207 */ 208 @serverbound struct NodeInfo { 209 210 enum ubyte ID = 4; 211 212 enum uint UNLIMITED = 0; 213 214 alias Plugin = Tuple!(uint, "id", string, "name", string, "version_"); 215 216 /** 217 * Informations about the games accepted by the node. There should be at least 218 * one combination of game/protocols that is also accepted by hub as indicated 219 * in HubInfo.gamesInfo, otherwise the node will never receive any player. 220 */ 221 uint[][ubyte] acceptedGames; 222 223 /** 224 * Maximum number of players accepted by node. 225 */ 226 uint max; 227 228 /** 229 * List of plugins currently loaded on the node. 230 * This field is used only for information purposes (as displaying the 231 * plugins in the querying protocol). 232 */ 233 Plugin[] plugins; 234 235 /** 236 * Port where the node is listening for connections, if the web admin protocol 237 * is active on the hub. 238 */ 239 ushort webAdminPort; 240 241 /** 242 * Optional informations about the server's software and system, 243 * similar to HubInfo's additionalJson field. 244 * Example: 245 * --- 246 * { 247 * "software": { 248 * "name": "Selery", 249 * "version": "0.1.0", 250 * "stable": true 251 * }, 252 * "system": { 253 * "os": "Windows 10", 254 * "cpu": "Intel(R) Core(TM) i7-5700U CPU @ 3.40GHz", 255 * "cores": 4, 256 * "ram": 8589934592 257 * } 258 * } 259 * --- 260 */ 261 JSONValue additionalJSON; 262 263 mixin IO!(acceptedGames, max, plugins, webAdminPort, additionalJSON); 264 265 }