| 1 | #ifndef PARTTY_H__ |
|---|
| 2 | #define PARTTY_H__ 1 |
|---|
| 3 | |
|---|
| 4 | #ifdef HAVE_CONFIG_H |
|---|
| 5 | #include "config.h" |
|---|
| 6 | #endif |
|---|
| 7 | |
|---|
| 8 | #include <stddef.h> |
|---|
| 9 | #include <stdint.h> |
|---|
| 10 | #include <stdexcept> |
|---|
| 11 | #include <cstring> |
|---|
| 12 | |
|---|
| 13 | #ifndef PARTTY_GATE_DIR |
|---|
| 14 | #define PARTTY_GATE_DIR "./var/socket/" |
|---|
| 15 | #endif |
|---|
| 16 | |
|---|
| 17 | #ifndef PARTTY_ARCHIVE_DIR |
|---|
| 18 | #define PARTTY_ARCHIVE_DIR \ |
|---|
| 19 | "./archive/archive/" |
|---|
| 20 | #endif |
|---|
| 21 | |
|---|
| 22 | #ifndef PARTTY_GATE_SESSION_BANNER |
|---|
| 23 | #define PARTTY_GATE_SESSION_BANNER \ |
|---|
| 24 | "Welcome to Partty hogehoge!\r\n\r\nSession name: " |
|---|
| 25 | #endif |
|---|
| 26 | |
|---|
| 27 | #ifndef PARTTY_GATE_PASSWORD_BANNER |
|---|
| 28 | #define PARTTY_GATE_PASSWORD_BANNER \ |
|---|
| 29 | "Password: " |
|---|
| 30 | #endif |
|---|
| 31 | |
|---|
| 32 | #ifndef PARTTY_SERVER_WELCOME_MESSAGE |
|---|
| 33 | #define PARTTY_SERVER_WELCOME_MESSAGE \ |
|---|
| 34 | "\r\n>Partty! connected.\r\n" |
|---|
| 35 | #endif |
|---|
| 36 | |
|---|
| 37 | #ifndef PARTTY_SESSION_START_MESSAGE |
|---|
| 38 | #define PARTTY_SESSION_START_MESSAGE \ |
|---|
| 39 | ">Partty! start\r\n" |
|---|
| 40 | #endif |
|---|
| 41 | |
|---|
| 42 | #ifndef PARTTY_SESSION_END_MESSAGE |
|---|
| 43 | #define PARTTY_SESSION_END_MESSAGE \ |
|---|
| 44 | ">Partty! end" |
|---|
| 45 | #endif |
|---|
| 46 | |
|---|
| 47 | |
|---|
| 48 | #define PARTTY_RAW_GATE_FLASH_CROSS_DOMAIN_SUPPORT |
|---|
| 49 | #ifndef PARTTY_RAW_GATE_FLASH_CROSS_DOMAIN_POLICY |
|---|
| 50 | #define PARTTY_RAW_GATE_FLASH_CROSS_DOMAIN_POLICY \ |
|---|
| 51 | "<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>" |
|---|
| 52 | #endif |
|---|
| 53 | |
|---|
| 54 | |
|---|
| 55 | namespace Partty { |
|---|
| 56 | |
|---|
| 57 | |
|---|
| 58 | static const unsigned short SERVER_DEFAULT_PORT = 2750; |
|---|
| 59 | static const unsigned short GATE_DEFAULT_PORT = 7777; |
|---|
| 60 | |
|---|
| 61 | static const size_t MAX_SESSION_NAME_LENGTH = 128; |
|---|
| 62 | static const size_t MIN_SESSION_NAME_LENGTH = 3; |
|---|
| 63 | static const size_t MAX_PASSWORD_LENGTH = 128; |
|---|
| 64 | static const size_t MAX_USER_NAME_LENGTH = 128; |
|---|
| 65 | |
|---|
| 66 | |
|---|
| 67 | static const char* const GATE_DIR = PARTTY_GATE_DIR; |
|---|
| 68 | static const char* const ARCHIVE_DIR = PARTTY_ARCHIVE_DIR; |
|---|
| 69 | static const char* const GATE_PASSWORD_BANNER = PARTTY_GATE_PASSWORD_BANNER; |
|---|
| 70 | static const char* const GATE_SESSION_BANNER = PARTTY_GATE_SESSION_BANNER; |
|---|
| 71 | static const char* const SERVER_WELCOME_MESSAGE = PARTTY_SERVER_WELCOME_MESSAGE; |
|---|
| 72 | static const char* const SESSION_START_MESSAGE = PARTTY_SESSION_START_MESSAGE; |
|---|
| 73 | static const char* const SESSION_END_MESSAGE = PARTTY_SESSION_END_MESSAGE; |
|---|
| 74 | |
|---|
| 75 | |
|---|
| 76 | static const uint8_t PROTOCOL_VERSION = 1; |
|---|
| 77 | |
|---|
| 78 | static const char NEGOTIATION_MAGIC_STRING[] = "Partty!"; |
|---|
| 79 | static const size_t NEGOTIATION_MAGIC_STRING_LENGTH = 7; |
|---|
| 80 | |
|---|
| 81 | struct negotiation_header_t { |
|---|
| 82 | char magic[NEGOTIATION_MAGIC_STRING_LENGTH]; // "Partty!" |
|---|
| 83 | uint8_t protocol_version; |
|---|
| 84 | uint16_t user_name_length; |
|---|
| 85 | uint16_t session_name_length; |
|---|
| 86 | uint16_t writable_password_length; |
|---|
| 87 | uint16_t readonly_password_length; |
|---|
| 88 | // char user_name[user_name_length]; |
|---|
| 89 | // char session_name[session_name_length]; |
|---|
| 90 | // char writable_password[writable_password_length]; |
|---|
| 91 | // char readonly_password[readonly_password_length]; |
|---|
| 92 | }; |
|---|
| 93 | |
|---|
| 94 | namespace negotiation_reply { |
|---|
| 95 | static const uint16_t SUCCESS = 0; |
|---|
| 96 | static const uint16_t PROTOCOL_MISMATCH = 1; |
|---|
| 97 | static const uint16_t SESSION_UNAVAILABLE = 2; |
|---|
| 98 | static const uint16_t SERVER_ERROR = 3; |
|---|
| 99 | static const uint16_t AUTHENTICATION_FAILED = 4; |
|---|
| 100 | }; |
|---|
| 101 | struct negotiation_reply_t { |
|---|
| 102 | uint16_t code; |
|---|
| 103 | uint16_t message_length; |
|---|
| 104 | // char message[message_length]; |
|---|
| 105 | }; |
|---|
| 106 | |
|---|
| 107 | |
|---|
| 108 | struct partty_error : public std::runtime_error { |
|---|
| 109 | partty_error(const std::string& message) : runtime_error(message) {} |
|---|
| 110 | virtual ~partty_error() throw() {} |
|---|
| 111 | }; |
|---|
| 112 | |
|---|
| 113 | struct initialize_error : public partty_error { |
|---|
| 114 | initialize_error(const std::string& message) : partty_error(message) {} |
|---|
| 115 | virtual ~initialize_error() throw() {} |
|---|
| 116 | }; |
|---|
| 117 | |
|---|
| 118 | struct io_error : public partty_error { |
|---|
| 119 | io_error(const std::string& message) : partty_error(message) {} |
|---|
| 120 | virtual ~io_error() throw() {} |
|---|
| 121 | }; |
|---|
| 122 | |
|---|
| 123 | struct io_end_error : public io_error { |
|---|
| 124 | io_end_error(const std::string& message) : io_error(message) {} |
|---|
| 125 | virtual ~io_end_error() throw() {} |
|---|
| 126 | }; |
|---|
| 127 | |
|---|
| 128 | |
|---|
| 129 | struct session_info_t; |
|---|
| 130 | struct session_info_ref_t { |
|---|
| 131 | inline session_info_ref_t(const session_info_t& src); |
|---|
| 132 | session_info_ref_t() {} |
|---|
| 133 | uint16_t user_name_length; |
|---|
| 134 | uint16_t session_name_length; |
|---|
| 135 | uint16_t readonly_password_length; |
|---|
| 136 | uint16_t writable_password_length; |
|---|
| 137 | const char* user_name; |
|---|
| 138 | const char* session_name; |
|---|
| 139 | const char* readonly_password; |
|---|
| 140 | const char* writable_password; |
|---|
| 141 | }; |
|---|
| 142 | |
|---|
| 143 | struct session_info_t { |
|---|
| 144 | inline session_info_t(const session_info_ref_t& ref); |
|---|
| 145 | session_info_t() {} |
|---|
| 146 | uint16_t user_name_length; |
|---|
| 147 | uint16_t session_name_length; |
|---|
| 148 | uint16_t writable_password_length; |
|---|
| 149 | uint16_t readonly_password_length; |
|---|
| 150 | char user_name[MAX_USER_NAME_LENGTH]; |
|---|
| 151 | char session_name[MAX_SESSION_NAME_LENGTH]; |
|---|
| 152 | char writable_password[MAX_PASSWORD_LENGTH]; |
|---|
| 153 | char readonly_password[MAX_PASSWORD_LENGTH]; |
|---|
| 154 | }; |
|---|
| 155 | |
|---|
| 156 | session_info_ref_t::session_info_ref_t(const session_info_t& src) : |
|---|
| 157 | user_name_length (src.user_name_length ), |
|---|
| 158 | session_name_length (src.session_name_length ), |
|---|
| 159 | readonly_password_length (src.readonly_password_length), |
|---|
| 160 | writable_password_length (src.writable_password_length), |
|---|
| 161 | user_name (src.user_name ), |
|---|
| 162 | session_name (src.session_name ), |
|---|
| 163 | readonly_password (src.readonly_password ), |
|---|
| 164 | writable_password (src.writable_password ) {} |
|---|
| 165 | |
|---|
| 166 | session_info_t::session_info_t(const session_info_ref_t& ref) : |
|---|
| 167 | session_name_length (ref.session_name_length ), |
|---|
| 168 | writable_password_length (ref.writable_password_length), |
|---|
| 169 | readonly_password_length (ref.readonly_password_length) |
|---|
| 170 | { |
|---|
| 171 | if( user_name_length > MAX_USER_NAME_LENGTH ) { |
|---|
| 172 | throw initialize_error("user name is too long"); |
|---|
| 173 | } |
|---|
| 174 | if( session_name_length > MAX_SESSION_NAME_LENGTH ) { |
|---|
| 175 | throw initialize_error("session name is too long"); |
|---|
| 176 | } |
|---|
| 177 | if( session_name_length < MIN_SESSION_NAME_LENGTH ) { |
|---|
| 178 | throw initialize_error("session name is too short"); |
|---|
| 179 | } |
|---|
| 180 | if( writable_password_length > MAX_PASSWORD_LENGTH ) { |
|---|
| 181 | throw initialize_error("operation password is too long"); |
|---|
| 182 | } |
|---|
| 183 | if( readonly_password_length > MAX_PASSWORD_LENGTH ) { |
|---|
| 184 | throw initialize_error("view-only password is too long"); |
|---|
| 185 | } |
|---|
| 186 | std::memcpy(user_name, ref.user_name, ref.user_name_length); |
|---|
| 187 | std::memcpy(session_name, ref.session_name, ref.session_name_length); |
|---|
| 188 | std::memcpy(writable_password, ref.writable_password, ref.writable_password_length); |
|---|
| 189 | std::memcpy(readonly_password, ref.readonly_password, ref.readonly_password_length); |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | |
|---|
| 193 | template <size_t Length> |
|---|
| 194 | struct line_t { |
|---|
| 195 | char str[Length]; |
|---|
| 196 | size_t len; |
|---|
| 197 | }; |
|---|
| 198 | struct gate_message_t { |
|---|
| 199 | line_t<MAX_SESSION_NAME_LENGTH> session_name; |
|---|
| 200 | line_t<MAX_PASSWORD_LENGTH> password; |
|---|
| 201 | }; |
|---|
| 202 | |
|---|
| 203 | |
|---|
| 204 | // Hostを待ち受け、Multiplexerをforkする |
|---|
| 205 | class ServerIMPL; |
|---|
| 206 | class Server { |
|---|
| 207 | public: |
|---|
| 208 | Server(int listen_socket); |
|---|
| 209 | ~Server(); |
|---|
| 210 | int run(void); |
|---|
| 211 | private: |
|---|
| 212 | ServerIMPL* impl; |
|---|
| 213 | Server(); |
|---|
| 214 | Server(const Server&); |
|---|
| 215 | }; |
|---|
| 216 | |
|---|
| 217 | |
|---|
| 218 | // Hostからの入力をゲストにコピーする |
|---|
| 219 | // ゲストからの入力をHostにコピーする |
|---|
| 220 | class MultiplexerIMPL; |
|---|
| 221 | class Multiplexer { |
|---|
| 222 | public: |
|---|
| 223 | Multiplexer(int host_socket, int gate_socket, |
|---|
| 224 | const session_info_ref_t& info); |
|---|
| 225 | ~Multiplexer(); |
|---|
| 226 | int run(void); |
|---|
| 227 | private: |
|---|
| 228 | MultiplexerIMPL* impl; |
|---|
| 229 | Multiplexer(); |
|---|
| 230 | Multiplexer(const Multiplexer&); |
|---|
| 231 | }; |
|---|
| 232 | |
|---|
| 233 | |
|---|
| 234 | // 新しい仮想端末を確保して、シェルを起動する |
|---|
| 235 | // 標準入力とServerからの入力をシェルにコピーする |
|---|
| 236 | // シェルの出力と標準出力をServerにコピーする |
|---|
| 237 | class HostIMPL; |
|---|
| 238 | class Host { |
|---|
| 239 | public: |
|---|
| 240 | struct config_t { |
|---|
| 241 | config_t(int _server_socket, |
|---|
| 242 | const session_info_ref_t& info_) : |
|---|
| 243 | server_socket(_server_socket), |
|---|
| 244 | info(info_) {} |
|---|
| 245 | public: |
|---|
| 246 | int lock_code; |
|---|
| 247 | private: |
|---|
| 248 | int server_socket; |
|---|
| 249 | const session_info_ref_t& info; |
|---|
| 250 | friend class HostIMPL; |
|---|
| 251 | }; |
|---|
| 252 | public: |
|---|
| 253 | Host(int server_socket, char lock_code, |
|---|
| 254 | const session_info_ref_t& info); |
|---|
| 255 | ~Host(); |
|---|
| 256 | int run(void); |
|---|
| 257 | private: |
|---|
| 258 | HostIMPL* impl; |
|---|
| 259 | Host(); |
|---|
| 260 | Host(const Host&); |
|---|
| 261 | }; |
|---|
| 262 | |
|---|
| 263 | |
|---|
| 264 | // ゲストを待ち受け、ファイルディスクリプタを |
|---|
| 265 | // Hostに転送する |
|---|
| 266 | class GateIMPL; |
|---|
| 267 | class Gate { |
|---|
| 268 | public: |
|---|
| 269 | struct config_t { |
|---|
| 270 | config_t(int listen_socket_) : |
|---|
| 271 | listen_socket(listen_socket_) {} |
|---|
| 272 | public: |
|---|
| 273 | private: |
|---|
| 274 | int listen_socket; |
|---|
| 275 | friend class GateIMPL; |
|---|
| 276 | }; |
|---|
| 277 | public: |
|---|
| 278 | Gate(int listen_socket); |
|---|
| 279 | ~Gate(); |
|---|
| 280 | int run(void); |
|---|
| 281 | void signal_end(void); |
|---|
| 282 | private: |
|---|
| 283 | GateIMPL* impl; |
|---|
| 284 | Gate(); |
|---|
| 285 | Gate(const Gate&); |
|---|
| 286 | }; |
|---|
| 287 | |
|---|
| 288 | |
|---|
| 289 | // プロトコルにTelnetではなくRawストリームを |
|---|
| 290 | // 使うGate |
|---|
| 291 | class RawGateIMPL; |
|---|
| 292 | class RawGate { |
|---|
| 293 | public: |
|---|
| 294 | RawGate(int listen_socket); |
|---|
| 295 | ~RawGate(); |
|---|
| 296 | int run(void); |
|---|
| 297 | void signal_end(void); |
|---|
| 298 | private: |
|---|
| 299 | RawGateIMPL* impl; |
|---|
| 300 | RawGate(); |
|---|
| 301 | RawGate(const RawGate&); |
|---|
| 302 | }; |
|---|
| 303 | |
|---|
| 304 | |
|---|
| 305 | } // namespace Partty |
|---|
| 306 | |
|---|
| 307 | #endif /* partty.h */ |
|---|
| 308 | |
|---|