github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/pfsagentd/jrpc.go (about) 1 // Copyright (c) 2015-2021, NVIDIA CORPORATION. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package main 5 6 import ( 7 "encoding/json" 8 "fmt" 9 ) 10 11 type jrpcRequestMethodAndIDStruct struct { 12 Method string `json:"method"` 13 ID uint64 `json:"id"` 14 } 15 16 type jrpcRequestStruct struct { 17 JSONrpc string `json:"jsonrpc"` 18 Method string `json:"method"` 19 ID uint64 `json:"id"` 20 Params [1]interface{} `json:"params"` 21 } 22 23 type jrpcResponseIDStruct struct { 24 ID uint64 `json:"id"` 25 } 26 27 type jrpcResponseIDAndErrorStruct struct { 28 ID uint64 `json:"id"` 29 Error string `json:"error"` 30 } 31 32 type jrpcResponseNoErrorStruct struct { 33 ID uint64 `json:"id"` 34 Result interface{} `json:"result"` 35 } 36 37 type jrpcResponseWithErrorStruct struct { 38 ID uint64 `json:"id"` 39 Error string `json:"error"` 40 Result interface{} `json:"result"` 41 } 42 43 func jrpcMarshalRequest(requestMethod string, request interface{}) (requestID uint64, requestBuf []byte, marshalErr error) { 44 var ( 45 jrpcRequest *jrpcRequestStruct 46 ) 47 48 globals.Lock() 49 requestID = globals.jrpcLastID + 1 50 globals.jrpcLastID = requestID 51 globals.Unlock() 52 53 jrpcRequest = &jrpcRequestStruct{ 54 JSONrpc: "2.0", 55 Method: requestMethod, 56 ID: requestID, 57 Params: [1]interface{}{request}, 58 } 59 60 requestBuf, marshalErr = json.Marshal(jrpcRequest) 61 62 return 63 } 64 65 func jrpcMarshalResponse(requestID uint64, responseError error, response interface{}) (responseBuf []byte, marshalErr error) { 66 var ( 67 jrpcResponse interface{} 68 ) 69 70 if nil == responseError { 71 if nil == response { 72 jrpcResponse = &jrpcResponseIDStruct{ 73 ID: requestID, 74 } 75 } else { 76 jrpcResponse = &jrpcResponseNoErrorStruct{ 77 ID: requestID, 78 Result: response, 79 } 80 } 81 } else { 82 if nil == response { 83 jrpcResponse = &jrpcResponseIDAndErrorStruct{ 84 ID: requestID, 85 Error: responseError.Error(), 86 } 87 } else { 88 jrpcResponse = &jrpcResponseWithErrorStruct{ 89 ID: requestID, 90 Error: responseError.Error(), 91 Result: response, 92 } 93 } 94 } 95 96 responseBuf, marshalErr = json.Marshal(jrpcResponse) 97 98 return 99 } 100 101 func jrpcUnmarshalRequestForMethodAndID(requestBuf []byte) (requestMethod string, requestID uint64, unmarshalErr error) { 102 var ( 103 jrpcRequest *jrpcRequestMethodAndIDStruct 104 ) 105 106 jrpcRequest = &jrpcRequestMethodAndIDStruct{} 107 108 unmarshalErr = json.Unmarshal(requestBuf, jrpcRequest) 109 110 if nil == unmarshalErr { 111 requestMethod = jrpcRequest.Method 112 requestID = jrpcRequest.ID 113 } 114 115 return 116 } 117 118 func jrpcUnmarshalRequest(requestID uint64, requestBuf []byte, request interface{}) (unmarshalErr error) { 119 var ( 120 jrpcRequest *jrpcRequestStruct 121 ) 122 123 jrpcRequest = &jrpcRequestStruct{ 124 Params: [1]interface{}{request}, 125 } 126 127 unmarshalErr = json.Unmarshal(requestBuf, jrpcRequest) 128 129 if (nil == unmarshalErr) && (requestID != jrpcRequest.ID) { 130 unmarshalErr = fmt.Errorf("requestID mismatch") 131 } 132 133 return 134 } 135 136 func jrpcUnmarshalResponseForIDAndError(responseBuf []byte) (requestID uint64, responseErr error, unmarshalErr error) { 137 var ( 138 jrpcResponse *jrpcResponseIDAndErrorStruct 139 ) 140 141 jrpcResponse = &jrpcResponseIDAndErrorStruct{} 142 143 unmarshalErr = json.Unmarshal(responseBuf, jrpcResponse) 144 145 if nil == unmarshalErr { 146 requestID = jrpcResponse.ID 147 if "" == jrpcResponse.Error { 148 responseErr = nil 149 } else { 150 responseErr = fmt.Errorf("%s", jrpcResponse.Error) 151 } 152 } 153 154 return 155 } 156 157 func jrpcUnmarshalResponse(requestID uint64, responseBuf []byte, response interface{}) (unmarshalErr error) { 158 var ( 159 jrpcResponse *jrpcResponseWithErrorStruct 160 ) 161 162 jrpcResponse = &jrpcResponseWithErrorStruct{ 163 Result: response, 164 } 165 166 unmarshalErr = json.Unmarshal(responseBuf, jrpcResponse) 167 168 if (nil == unmarshalErr) && (requestID != jrpcResponse.ID) { 169 unmarshalErr = fmt.Errorf("requestID mismatch") 170 } 171 172 return 173 }