1 /** 2 * Low level wire protocol for RPC. 3 */ 4 module vibe.rpcchannel.protocol; 5 6 import std.exception : enforceEx; 7 import vibe.data.json; 8 import vibe.core.stream; 9 import vibe.rpcchannel.base; 10 11 /* 12 * Problem : vibe.d does not really support JSON deserialization from a range 13 * Solution : Always read & buffer a line and use line terminators after every 14 * JSON entity. 15 * 16 * Request protocol: 17 * 18 * RequestType 19 * |----=call-->CallMessage-->parameters*any 20 * --------------| 21 * |----=disconnect 22 * 23 * Reponse protocol: 24 * 25 * ResponseType |---=error-->ErrorMessage 26 * --------------| 27 * |---=result->ResultMessage-->hasResult?any:none 28 * | 29 * |---=event-->EventMessage-->parameters*any 30 * | 31 * |---=disconnect 32 */ 33 34 /** 35 * Type of message sent to server. 36 */ 37 enum RequestType 38 { 39 call, /// call a function 40 disconnect /// disconnect 41 } 42 43 /** 44 * Message sent to server to call a function. 45 */ 46 struct CallMessage 47 { 48 uint id; /// request id 49 string target; /// function target name 50 string mangle; /// function mangle for overloading 51 uint parameters; /// number of parameters following this message 52 } 53 54 /** 55 * Type of message sent to client. 56 */ 57 enum ResponseType 58 { 59 disconnect, /// Disconnect the session 60 error, /// An error occured 61 result, /// A function result is returned 62 event /// A event occured 63 } 64 65 /** 66 * If an error is being send, type of error. 67 */ 68 enum ErrorType 69 { 70 notImplemented, /// calling an unimplemented endpoint 71 parameterMismatch, /// invalid number of parameters or parser error 72 internalError /// called method threw an Exception 73 } 74 75 /** 76 * Message sent to client as response to a call if an error occured. 77 */ 78 struct ErrorMessage 79 { 80 uint id; /// The request id repeated 81 ErrorType type; /// Type of error 82 83 @optional string message; /// In debug mode only 84 @optional string file; /// In debug mode only 85 @optional uint line; /// In debug mode only 86 } 87 88 /** 89 * Message sent to client as response to a call if call was sucessfull. 90 */ 91 struct ResultMessage 92 { 93 uint id; /// The request id repeated 94 bool hasResult; /// Whether there's a result value after this message 95 } 96 97 /** 98 * Message sent to client if an event occurs. 99 */ 100 struct EventMessage 101 { 102 string target; /// Name of the event 103 uint parameters; /// Number of parameters following this message 104 } 105 106 /** 107 * Read one line from stream and deserialize the json value. 108 */ 109 T deserializeJsonLine(T)(InputStream stream) 110 { 111 import vibe.stream.operations; 112 113 // TODO: Avoid GC 114 auto line = cast(string) stream.readLine(size_t.max, "\n"); 115 116 enforceEx!RPCException(line.length != 0); 117 118 static if (!is(T == void)) 119 return deserializeJson!T(line); 120 } 121 122 /** 123 * Serialize the json value and write as one line to stream. 124 */ 125 void serializeToJsonLine(T)(OutputStream stream, T value) 126 { 127 auto str = serializeToJsonString(value); 128 stream.write(str); 129 stream.write("\n"); 130 } 131 132 /** 133 * Skip num objects on stream. 134 */ 135 void skipParameters(Stream stream, size_t num) 136 { 137 // skip remaining params 138 for (size_t i = 0; i < num; i++) 139 { 140 stream.deserializeJsonLine!void(); 141 } 142 }