@@ -147,11 +147,10 @@ func NewConn(ctx context.Context, s Stream, options ...Options) *Conn {
147
147
// the default canceller does nothing
148
148
conn .Canceler = defaultCanceler
149
149
}
150
-
151
- go func () {
152
- conn .err = conn .Run (ctx )
153
- close (conn .done )
154
- }()
150
+ if conn .logger == nil {
151
+ // the default logger does nothing
152
+ conn .logger = zap .NewNop ()
153
+ }
155
154
156
155
return conn
157
156
}
@@ -170,20 +169,21 @@ func (c *Conn) Write(p []byte) (n int, err error) {
170
169
func (c * Conn ) Call (ctx context.Context , method string , params , result interface {}) error {
171
170
jsonParams , err := marshalToEmbedded (params )
172
171
if err != nil {
173
- return xerrors .Errorf ("failed to marshalling call parameters: %v" , err )
172
+ return xerrors .Errorf ("failed to marshaling call parameters: %v" , err )
174
173
}
175
- id := ID {Number : c .seq .Add (1 )}
176
174
175
+ id := ID {Number : c .seq .Add (1 )}
177
176
req := & Request {
178
- ID : & id ,
179
- Method : method ,
180
- Params : jsonParams ,
177
+ JSONRPC : Version ,
178
+ ID : & id ,
179
+ Method : method ,
180
+ Params : jsonParams ,
181
181
}
182
182
183
183
// marshal the request now it is complete
184
- data , err := gojay .Marshal (req )
184
+ data , err := gojay .MarshalJSONObject (req )
185
185
if err != nil {
186
- return xerrors .Errorf ("failed to marshalling call request: %v" , err )
186
+ return xerrors .Errorf ("failed to marshaling call request: %v" , err )
187
187
}
188
188
189
189
rchan := make (chan * Response )
@@ -203,8 +203,9 @@ func (c *Conn) Call(ctx context.Context, method string, params, result interface
203
203
}()
204
204
205
205
start := time .Now ()
206
- c .logger .Info (Send .String (),
207
- zap .String ("id" , id .String ()),
206
+ c .logger .Debug (Send ,
207
+ zap .String ("req.JSONRPC" , req .JSONRPC ),
208
+ zap .Any ("id" , id ),
208
209
zap .String ("req.method" , req .Method ),
209
210
zap .Any ("req.params" , req .Params ),
210
211
)
@@ -214,8 +215,9 @@ func (c *Conn) Call(ctx context.Context, method string, params, result interface
214
215
215
216
select {
216
217
case resp := <- rchan :
217
- c .logger .Info (Receive .String (),
218
- zap .String ("id" , id .String ()),
218
+ c .logger .Debug (Receive ,
219
+ zap .String ("req.JSONRPC" , req .JSONRPC ),
220
+ zap .Any ("id" , id ),
219
221
zap .Duration ("elapsed" , time .Since (start )),
220
222
zap .String ("req.method" , req .Method ),
221
223
zap .Any ("resp.Result" , resp .Result ),
@@ -228,7 +230,7 @@ func (c *Conn) Call(ctx context.Context, method string, params, result interface
228
230
if result == nil || resp .Result == nil {
229
231
return nil
230
232
}
231
- if err := gojay .Unsafe .Unmarshal (* resp .Result . EmbeddedJSON , result ); err != nil {
233
+ if err := gojay .Unsafe .Unmarshal (* resp .Result , result ); err != nil {
232
234
return xerrors .Errorf ("failed to unmarshalling result: %v" , err )
233
235
}
234
236
return nil
@@ -255,27 +257,33 @@ func (c *Conn) Reply(ctx context.Context, req *Request, result interface{}, err
255
257
}
256
258
257
259
elapsed := time .Since (handling .start )
258
- var raw * RawMessage
259
- if err == nil {
260
- raw , err = marshalToEmbedded (result )
261
- }
262
260
263
261
resp := & Response {
264
- ID : req . ID ,
265
- Result : raw ,
262
+ JSONRPC : Version ,
263
+ ID : req . ID ,
266
264
}
267
-
268
- if err != nil {
269
- resp .Error = Errorf (0 , "%s" , err )
265
+ if err == nil {
266
+ if resp .Result , err = marshalToEmbedded (result ); err != nil {
267
+ return err
268
+ }
269
+ } else {
270
+ resp .Error = New (CodeParseError , err )
270
271
}
271
272
272
273
data , err := gojay .Marshal (resp )
273
274
if err != nil {
275
+ c .logger .Error (Send ,
276
+ zap .Any ("resp.ID" , resp .ID .Number ),
277
+ zap .Duration ("elapsed" , elapsed ),
278
+ zap .String ("req.Method" , req .Method ),
279
+ zap .Any ("resp.Result" , resp .Result ),
280
+ zap .Error (err ),
281
+ )
274
282
return err
275
283
}
276
284
277
- c .logger .Info (Send . String () ,
278
- zap .String ("resp.ID" , resp .ID . String () ),
285
+ c .logger .Debug (Send ,
286
+ zap .Any ("resp.ID" , resp .ID ),
279
287
zap .Duration ("elapsed" , elapsed ),
280
288
zap .String ("req.Method" , req .Method ),
281
289
zap .Any ("resp.Result" , resp .Result ),
@@ -291,21 +299,22 @@ func (c *Conn) Reply(ctx context.Context, req *Request, result interface{}, err
291
299
292
300
// Notify is called to send a notification request over the connection.
293
301
func (c * Conn ) Notify (ctx context.Context , method string , params interface {}) error {
294
- jsonParams , err := marshalToEmbedded (params )
302
+ prms , err := marshalToEmbedded (params )
295
303
if err != nil {
296
- return xerrors . Errorf ("failed to marshalling notify parameters: %v" , err )
304
+ return Errorf (CodeParseError , "failed to marshaling notify parameters: %v" , err )
297
305
}
298
306
299
307
req := & NotificationMessage {
300
- Method : method ,
301
- Params : jsonParams ,
308
+ JSONRPC : Version ,
309
+ Method : method ,
310
+ Params : prms ,
302
311
}
303
312
data , err := gojay .MarshalJSONObject (req )
304
313
if err != nil {
305
- return xerrors . Errorf ("failed to marshalling notify request: %v" , err )
314
+ return Errorf (CodeParseError , "failed to marshaling notify request: %v" , err )
306
315
}
307
316
308
- c .logger .Info (Send . String () ,
317
+ c .logger .Debug (Send ,
309
318
zap .String ("req.Method" , req .Method ),
310
319
zap .Any ("req.Params" , req .Params ),
311
320
)
@@ -347,17 +356,6 @@ func (c *Conn) deliver(ctx context.Context, q chan queue, request *Request) bool
347
356
}
348
357
}
349
358
350
- // combined has all the fields of both Request and Response.
351
- // We can decode this and then work out which it is.
352
- type combined struct {
353
- VersionTag Message `json:"jsonrpc"`
354
- ID * ID `json:"id,omitempty"`
355
- Method string `json:"method"`
356
- Params * RawMessage `json:"params,omitempty"`
357
- Result * RawMessage `json:"result,omitempty"`
358
- Error * Error `json:"error,omitempty"`
359
- }
360
-
361
359
// Run run the jsonrpc2 server.
362
360
func (c * Conn ) Run (ctx context.Context ) (err error ) {
363
361
q := make (chan queue , c .capacity )
@@ -374,22 +372,21 @@ func (c *Conn) Run(ctx context.Context) (err error) {
374
372
}()
375
373
376
374
for {
377
- var data []byte
378
- // get the data for a message
379
- _ , err = c .stream .Read (ctx , data )
375
+ data := make ([]byte , 0 , 512 )
376
+ _ , err = c .stream .Read (ctx , data ) // get the data for a message
380
377
if err != nil {
381
- // the stream failed, we cannot continue
382
- return err
378
+ return err // the stream failed, we cannot continue
383
379
}
384
380
385
381
// read a combined message
386
- msg := & combined {}
387
- if err := gojay .Unsafe .Unmarshal (data , msg ); err != nil {
382
+ msg := new ( Combined )
383
+ if err := gojay .Unsafe .UnmarshalJSONObject (data , msg ); err != nil {
388
384
// a badly formed message arrived, log it and continue
389
385
// we trust the stream to have isolated the error to just this message
390
- c .logger .Info (Receive . String () ,
391
- zap .Error (Errorf (0 , "unmarshal failed: %v" , err )),
386
+ c .logger .Debug (Receive ,
387
+ zap .Error (Errorf (CodeParseError , "unmarshal failed: %v" , err )),
392
388
)
389
+
393
390
continue
394
391
}
395
392
@@ -398,32 +395,43 @@ func (c *Conn) Run(ctx context.Context) (err error) {
398
395
case msg .Method != "" :
399
396
// if method is set it must be a request
400
397
req := & Request {
401
- Method : msg .Method ,
402
- Params : msg .Params ,
403
- ID : msg .ID ,
398
+ JSONRPC : Version ,
399
+ Method : msg .Method ,
400
+ Params : msg .Params ,
401
+ ID : msg .ID ,
404
402
}
405
403
if req .IsNotify () {
406
- c .logger .Info (Receive .String (), zap .String ("req.ID" , req .ID .String ()), zap .String ("req.Method" , req .Method ), zap .Any ("req.Params" , req .Params ))
404
+ c .logger .Debug (Receive ,
405
+ zap .Any ("req.ID" , req .ID ),
406
+ zap .String ("req.Method" , req .Method ),
407
+ zap .Any ("req.Params" , req .Params ),
408
+ )
407
409
c .deliver (ctx , q , req )
408
- } else {
409
- // we have a Call, add to the processor queue
410
- reqCtx , reqCancel := context .WithCancel (ctx )
411
- defer reqCancel ()
412
- m , ok := c .handling .Load ().(handlingMap )
413
- if ! ok {
414
- return errLoadhandlingMap
415
- }
416
- m [* req .ID ] = handling {
417
- request : req ,
418
- cancel : reqCancel ,
419
- start : time .Now (),
420
- }
421
- c .handling .Store (m )
422
- c .logger .Info (Receive .String (), zap .String ("req.ID" , req .ID .String ()), zap .String ("req.Method" , req .Method ), zap .Any ("req.Params" , req .Params ))
423
- if ! c .deliver (reqCtx , q , req ) {
424
- // queue is full, reject the message by directly replying
425
- c .Reply (ctx , req , nil , Errorf (CodeServerOverloaded , "no room in queue" ))
426
- }
410
+
411
+ return
412
+ }
413
+
414
+ // we have a Call, add to the processor queue
415
+ reqCtx , reqCancel := context .WithCancel (ctx )
416
+ m , ok := c .handling .Load ().(handlingMap )
417
+ if ! ok {
418
+ return errLoadhandlingMap
419
+ }
420
+ m [* req .ID ] = handling {
421
+ request : req ,
422
+ cancel : reqCancel ,
423
+ start : time .Now (),
424
+ }
425
+ c .handling .Store (m )
426
+
427
+ c .logger .Debug (Receive ,
428
+ zap .Any ("req.ID" , req .ID ),
429
+ zap .String ("req.Method" , req .Method ),
430
+ zap .Any ("req.Params" , req .Params ),
431
+ )
432
+ if ! c .deliver (reqCtx , q , req ) {
433
+ // queue is full, reject the message by directly replying
434
+ c .Reply (ctx , req , nil , Errorf (CodeServerOverloaded , "no room in queue" ))
427
435
}
428
436
429
437
case msg .ID != nil :
@@ -437,49 +445,36 @@ func (c *Conn) Run(ctx context.Context) (err error) {
437
445
delete (m , * msg .ID )
438
446
}
439
447
c .pending .Store (m )
448
+
440
449
// and send the reply to the channel
441
450
resp := & Response {
442
- Result : msg .Result ,
443
- Error : msg .Error ,
444
- ID : msg .ID ,
451
+ JSONRPC : Version ,
452
+ Result : msg .Result ,
453
+ Error : msg .Error ,
454
+ ID : msg .ID ,
445
455
}
446
456
rchan <- resp
447
457
close (rchan )
448
458
449
459
default :
450
- c .logger .Info (Receive . String () , zap .Error (Errorf (0 , "message not a call, notify or response, ignoring" )))
460
+ c .logger .Error (Receive , zap .Error (Errorf (CodeInvalidParams , "message not a call, notify or response, ignoring" )))
451
461
}
452
462
}
453
463
}
454
464
455
- // Direction is used to indicate to a logger whether the logged message was being
456
- // sent or received.
457
- type Direction bool
458
-
459
465
const (
460
466
// Send indicates the message is outgoing.
461
- Send = Direction ( true )
467
+ Send = "send"
462
468
// Receive indicates the message is incoming.
463
- Receive = Direction ( false )
469
+ Receive = "receive"
464
470
)
465
471
466
- func (d Direction ) String () string {
467
- switch d {
468
- case Send :
469
- return "send"
470
- case Receive :
471
- return "receive"
472
- default :
473
- panic ("unreachable" )
474
- }
475
- }
476
-
477
472
func marshalToEmbedded (obj interface {}) (* RawMessage , error ) {
478
- data , err := gojay .Marshal (obj )
473
+ data , err := gojay .MarshalAny (obj )
479
474
if err != nil {
480
475
return nil , err
481
476
}
482
- raw := gojay .EmbeddedJSON (data )
477
+ raw := RawMessage ( gojay .EmbeddedJSON (data ) )
483
478
484
- return & RawMessage { EmbeddedJSON : & raw } , nil
479
+ return & raw , nil
485
480
}
0 commit comments