@@ -5,31 +5,152 @@ import (
5
5
"errors"
6
6
"fmt"
7
7
"io"
8
+ "log"
8
9
"reflect"
10
+ "sync"
11
+ "sync/atomic"
12
+ "time"
9
13
)
10
14
11
15
type JSONRPCServer struct {
12
16
writer io.Writer
13
17
14
18
handlers map [string ]* RPCHandler
19
+ nextId atomic.Int64
20
+
21
+ responseChannelsMutex sync.Mutex
22
+ responseChannels map [int64 ]chan JSONRPCResponse
15
23
}
16
24
17
25
func NewJSONRPCServer (writer io.Writer , handlers map [string ]* RPCHandler ) * JSONRPCServer {
18
26
return & JSONRPCServer {
19
- writer : writer ,
20
- handlers : handlers ,
27
+ writer : writer ,
28
+ handlers : handlers ,
29
+ responseChannels : make (map [int64 ]chan JSONRPCResponse ),
30
+ nextId : atomic.Int64 {},
31
+ }
32
+ }
33
+
34
+ func (s * JSONRPCServer ) Request (method string , params map [string ]interface {}, result interface {}) * JSONRPCResponseError {
35
+ id := s .nextId .Add (1 )
36
+ request := JSONRPCRequest {
37
+ JSONRPC : "2.0" ,
38
+ Method : method ,
39
+ Params : params ,
40
+ ID : id ,
41
+ }
42
+ requestBytes , err := json .Marshal (request )
43
+ if err != nil {
44
+ return & JSONRPCResponseError {
45
+ Code : - 32700 ,
46
+ Message : "Parse error" ,
47
+ Data : err ,
48
+ }
49
+ }
50
+
51
+ // log.Printf("Sending RPC request: Method=%s, Params=%v, ID=%d", method, params, id)
52
+
53
+ responseChan := make (chan JSONRPCResponse , 1 )
54
+ s .responseChannelsMutex .Lock ()
55
+ s .responseChannels [id ] = responseChan
56
+ s .responseChannelsMutex .Unlock ()
57
+ defer func () {
58
+ s .responseChannelsMutex .Lock ()
59
+ delete (s .responseChannels , id )
60
+ s .responseChannelsMutex .Unlock ()
61
+ }()
62
+
63
+ _ , err = s .writer .Write (requestBytes )
64
+ if err != nil {
65
+ return & JSONRPCResponseError {
66
+ Code : - 32603 ,
67
+ Message : "Internal error" ,
68
+ Data : err ,
69
+ }
70
+ }
71
+
72
+ timeout := time .After (5 * time .Second )
73
+ select {
74
+ case response := <- responseChan :
75
+ if response .Error != nil {
76
+ return response .Error
77
+ }
78
+
79
+ rawResult , err := json .Marshal (response .Result )
80
+ if err != nil {
81
+ return & JSONRPCResponseError {
82
+ Code : - 32603 ,
83
+ Message : "Internal error" ,
84
+ Data : err ,
85
+ }
86
+ }
87
+
88
+ if err := json .Unmarshal (rawResult , result ); err != nil {
89
+ return & JSONRPCResponseError {
90
+ Code : - 32603 ,
91
+ Message : "Internal error" ,
92
+ Data : err ,
93
+ }
94
+ }
95
+
96
+ return nil
97
+ case <- timeout :
98
+ return & JSONRPCResponseError {
99
+ Code : - 32603 ,
100
+ Message : "Internal error" ,
101
+ Data : "timeout waiting for response" ,
102
+ }
21
103
}
22
104
}
23
105
106
+ type JSONRPCMessage struct {
107
+ Method * string `json:"method,omitempty"`
108
+ ID * int64 `json:"id,omitempty"`
109
+ }
110
+
24
111
func (s * JSONRPCServer ) HandleMessage (data []byte ) error {
112
+ // Data will either be a JSONRPCRequest or JSONRPCResponse object
113
+ // We need to determine which one it is
114
+ var raw JSONRPCMessage
115
+ err := json .Unmarshal (data , & raw )
116
+ if err != nil {
117
+ errorResponse := JSONRPCResponse {
118
+ JSONRPC : "2.0" ,
119
+ Error : & JSONRPCResponseError {
120
+ Code : - 32700 ,
121
+ Message : "Parse error" ,
122
+ },
123
+ ID : 0 ,
124
+ }
125
+ return s .writeResponse (errorResponse )
126
+ }
127
+
128
+ if raw .Method == nil && raw .ID != nil {
129
+ var resp JSONRPCResponse
130
+ if err := json .Unmarshal (data , & resp ); err != nil {
131
+ fmt .Println ("error unmarshalling response" , err )
132
+ return err
133
+ }
134
+
135
+ s .responseChannelsMutex .Lock ()
136
+ responseChan , ok := s .responseChannels [* raw .ID ]
137
+ s .responseChannelsMutex .Unlock ()
138
+ if ok {
139
+ responseChan <- resp
140
+ } else {
141
+ log .Println ("No response channel found for ID" , resp .ID )
142
+ }
143
+ return nil
144
+ }
145
+
25
146
var request JSONRPCRequest
26
- err : = json .Unmarshal (data , & request )
147
+ err = json .Unmarshal (data , & request )
27
148
if err != nil {
28
149
errorResponse := JSONRPCResponse {
29
150
JSONRPC : "2.0" ,
30
- Error : map [ string ] interface {} {
31
- "code" : - 32700 ,
32
- "message" : "Parse error" ,
151
+ Error : & JSONRPCResponseError {
152
+ Code : - 32700 ,
153
+ Message : "Parse error" ,
33
154
},
34
155
ID : 0 ,
35
156
}
@@ -41,9 +162,9 @@ func (s *JSONRPCServer) HandleMessage(data []byte) error {
41
162
if ! ok {
42
163
errorResponse := JSONRPCResponse {
43
164
JSONRPC : "2.0" ,
44
- Error : map [ string ] interface {} {
45
- "code" : - 32601 ,
46
- "message" : "Method not found" ,
165
+ Error : & JSONRPCResponseError {
166
+ Code : - 32601 ,
167
+ Message : "Method not found" ,
47
168
},
48
169
ID : request .ID ,
49
170
}
@@ -54,10 +175,10 @@ func (s *JSONRPCServer) HandleMessage(data []byte) error {
54
175
if err != nil {
55
176
errorResponse := JSONRPCResponse {
56
177
JSONRPC : "2.0" ,
57
- Error : map [ string ] interface {} {
58
- "code" : - 32603 ,
59
- "message" : "Internal error" ,
60
- "data" : err .Error (),
178
+ Error : & JSONRPCResponseError {
179
+ Code : - 32603 ,
180
+ Message : "Internal error" ,
181
+ Data : err .Error (),
61
182
},
62
183
ID : request .ID ,
63
184
}
0 commit comments