1 /** 2 * Общий модуль для протоколов 3 * 4 * Copyright: (c) 2015-2017, Milofon Project. 5 * License: Subject to the terms of the BSD license, as written in the included LICENSE.txt file. 6 * Author: <m.galanin@milofon.org> Maksim Galanin 7 * Date: 2018-01-28 8 */ 9 10 module dango.service.protocol.core; 11 12 public 13 { 14 import std.typecons : Nullable; 15 16 import proped : Properties; 17 18 import dango.service.serializer : Serializer, UniNode; 19 import dango.service.dispatcher : Dispatcher; 20 import dango.service.transport : ClientTransport; 21 } 22 23 24 /** 25 * Интерфейс серверного Rpc протокола 26 */ 27 interface RpcServerProtocol 28 { 29 /** 30 * Инициализация протокола 31 * Params: 32 * dispatcher = Диспетчер вызовов 33 * serializer = Сериализатор 34 * config = Конфигурация протокола 35 */ 36 void initialize(Dispatcher dispatcher, Serializer serializer, Properties config); 37 38 /** 39 * Метод-обработик входящейго запроса 40 * Params: 41 * data = Бинарные данные 42 * Return: Ответ в бинарном виде 43 */ 44 ubyte[] handle(ubyte[] data); 45 } 46 47 48 /** 49 * Интерфейс клиентского Rpc протокола 50 */ 51 interface RpcClientProtocol 52 { 53 /** 54 * Инициализация клиентского протокола 55 * Params: 56 * serializer = Сериализатор 57 * config = Конфигурация протокола 58 */ 59 void initialize(Serializer serializer, ClientTransport transport); 60 61 /** 62 * Отправляет запрос удаленной команды 63 * Params: 64 * cmd = Команда 65 * params = Параметры 66 * Return: Результат выполнения удаленной команды (result) 67 */ 68 UniNode request(string cmd, UniNode params); 69 } 70 71 72 /** 73 * Сообщение об ошибке 74 */ 75 struct RpcError(T) 76 { 77 int code; 78 string message; 79 Nullable!T data; 80 } 81 82 83 /** 84 * Создает новое сообщение об ошибке по коду 85 * Params: 86 * code = Код ошибки 87 */ 88 RpcError!T createEmptyErrorByCode(T = ubyte)(int code) 89 { 90 RpcError!T result; 91 result.code = code; 92 switch (code) 93 { 94 case -32700: 95 result.message = "Parse error"; 96 break; 97 case -32600: 98 result.message = "Invalid Request"; 99 break; 100 case -32601: 101 result.message = "Method not found"; 102 break; 103 case -32602: 104 result.message = "Invalid params"; 105 break; 106 case -32603: 107 result.message = "Internal error"; 108 break; 109 default: 110 result.message = "Server error"; 111 break; 112 } 113 return result; 114 } 115 116 117 /** 118 * Создает новое сообщение об ошибке по коду с доп. данными 119 * Params: 120 * code = Код ошибки 121 * data = Доп. данные 122 */ 123 RpcError!T createErrorByCode(T)(int code, T data) 124 { 125 auto ret = createEmptyErrorByCode!T(code); 126 ret.data = Nullable!T(data); 127 return ret; 128 } 129 130 131 /** 132 * Предопределенные коды ошибок 133 */ 134 enum ErrorCode 135 { 136 PARSE_ERROR = -32700, 137 INVALID_REQUEST = -32600, 138 METHOD_NOT_FOUND = -32601, 139 INVALID_PARAMS = -32602, 140 INTERNAL_ERROR = -32603, 141 SERVER_ERROR = -32000 142 } 143 144 145 /** 146 * Ошибка Rpc 147 */ 148 class RpcException : Exception 149 { 150 private RpcError!UniNode _error; 151 152 this(int code, string message, string file = __FILE__, 153 size_t line = __LINE__, Throwable next = null) 154 { 155 _error.code = code; 156 _error.message = message; 157 super(message, file, line, next); 158 } 159 160 161 this(int code, string message, UniNode data, string file = __FILE__, 162 size_t line = __LINE__, Throwable next = null) 163 { 164 _error.data = data; 165 this(code, message, file, line, next); 166 } 167 168 169 this(RpcError!UniNode error, string file = __FILE__, size_t line = __LINE__, Throwable next = null) 170 { 171 _error = error; 172 super(error.message, file, line, next); 173 } 174 175 176 RpcError!UniNode error() @property nothrow 177 { 178 return _error; 179 } 180 }