blob: e9164b0bc958829b4eb2d6b139b2fdb50e0febfa [file] [log] [blame]
Ian Cottrell877f9c42021-02-09 22:45:26 -05001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec.
6// https://www.jsonrpc.org/specification
7// It is intended to be compatible with other implementations at the wire level.
8package jsonrpc2
9
10import (
11 "context"
12 "errors"
13)
14
15var (
16 // ErrIdleTimeout is returned when serving timed out waiting for new connections.
17 ErrIdleTimeout = errors.New("timed out waiting for new connections")
Bryan C. Mills5d35a752022-02-28 10:55:20 -050018
19 // ErrNotHandled is returned from a Handler or Preempter to indicate it did
20 // not handle the request.
21 //
22 // If a Handler returns ErrNotHandled, the server replies with
23 // ErrMethodNotFound.
Ian Cottrell877f9c42021-02-09 22:45:26 -050024 ErrNotHandled = errors.New("JSON RPC not handled")
Bryan C. Mills5d35a752022-02-28 10:55:20 -050025
Ian Cottrell877f9c42021-02-09 22:45:26 -050026 // ErrAsyncResponse is returned from a handler to indicate it will generate a
27 // response asynchronously.
Bryan C. Mills5d35a752022-02-28 10:55:20 -050028 //
29 // ErrAsyncResponse must not be returned for notifications,
30 // which do not receive responses.
Ian Cottrell877f9c42021-02-09 22:45:26 -050031 ErrAsyncResponse = errors.New("JSON RPC asynchronous response")
32)
33
34// Preempter handles messages on a connection before they are queued to the main
35// handler.
36// Primarily this is used for cancel handlers or notifications for which out of
37// order processing is not an issue.
38type Preempter interface {
Bryan C. Mills5d35a752022-02-28 10:55:20 -050039 // Preempt is invoked for each incoming request before it is queued for handling.
40 //
41 // If Preempt returns ErrNotHandled, the request will be queued,
42 // and eventually passed to a Handle call.
43 //
44 // Otherwise, the result and error are processed as if returned by Handle.
45 //
46 // Preempt must not block. (The Context passed to it is for Values only.)
47 Preempt(ctx context.Context, req *Request) (result interface{}, err error)
Ian Cottrell877f9c42021-02-09 22:45:26 -050048}
49
Bryan C. Millsbc2e3ae2022-02-28 11:24:36 -050050// A PreempterFunc implements the Preempter interface for a standalone Preempt function.
51type PreempterFunc func(ctx context.Context, req *Request) (interface{}, error)
52
53func (f PreempterFunc) Preempt(ctx context.Context, req *Request) (interface{}, error) {
54 return f(ctx, req)
55}
56
57var _ Preempter = PreempterFunc(nil)
58
Ian Cottrell877f9c42021-02-09 22:45:26 -050059// Handler handles messages on a connection.
60type Handler interface {
Bryan C. Mills5d35a752022-02-28 10:55:20 -050061 // Handle is invoked sequentially for each incoming request that has not
62 // already been handled by a Preempter.
63 //
64 // If the Request has a nil ID, Handle must return a nil result,
65 // and any error may be logged but will not be reported to the caller.
66 //
67 // If the Request has a non-nil ID, Handle must return either a
68 // non-nil, JSON-marshalable result, or a non-nil error.
69 //
70 // The Context passed to Handle will be canceled if the
71 // connection is broken or the request is canceled or completed.
72 // (If Handle returns ErrAsyncResponse, ctx will remain uncanceled
73 // until either Cancel or Respond is called for the request's ID.)
74 Handle(ctx context.Context, req *Request) (result interface{}, err error)
Ian Cottrell877f9c42021-02-09 22:45:26 -050075}
76
77type defaultHandler struct{}
78
79func (defaultHandler) Preempt(context.Context, *Request) (interface{}, error) {
80 return nil, ErrNotHandled
81}
82
83func (defaultHandler) Handle(context.Context, *Request) (interface{}, error) {
84 return nil, ErrNotHandled
85}
86
Bryan C. Millsbc2e3ae2022-02-28 11:24:36 -050087// A HandlerFunc implements the Handler interface for a standalone Handle function.
Rob Findleyf4516902021-05-18 13:33:26 -040088type HandlerFunc func(ctx context.Context, req *Request) (interface{}, error)
89
90func (f HandlerFunc) Handle(ctx context.Context, req *Request) (interface{}, error) {
91 return f(ctx, req)
92}
93
Bryan C. Millsbc2e3ae2022-02-28 11:24:36 -050094var _ Handler = HandlerFunc(nil)
95
Rob Findley00129ff2021-05-19 11:51:44 -040096// async is a small helper for operations with an asynchronous result that you
97// can wait for.
Ian Cottrell877f9c42021-02-09 22:45:26 -050098type async struct {
Bryan C. Mills5d35a752022-02-28 10:55:20 -050099 ready chan struct{} // closed when done
100 firstErr chan error // 1-buffered; contains either nil or the first non-nil error
Ian Cottrell877f9c42021-02-09 22:45:26 -0500101}
102
Rob Findleyfe2294a2021-06-25 11:49:46 -0400103func newAsync() *async {
104 var a async
Ian Cottrell877f9c42021-02-09 22:45:26 -0500105 a.ready = make(chan struct{})
Bryan C. Mills5d35a752022-02-28 10:55:20 -0500106 a.firstErr = make(chan error, 1)
107 a.firstErr <- nil
Rob Findleyfe2294a2021-06-25 11:49:46 -0400108 return &a
Ian Cottrell877f9c42021-02-09 22:45:26 -0500109}
110
111func (a *async) done() {
112 close(a.ready)
113}
114
Ian Cottrellb0e994d2021-03-25 22:16:30 -0400115func (a *async) isDone() bool {
116 select {
117 case <-a.ready:
118 return true
119 default:
120 return false
121 }
122}
123
Ian Cottrell877f9c42021-02-09 22:45:26 -0500124func (a *async) wait() error {
125 <-a.ready
Bryan C. Mills5d35a752022-02-28 10:55:20 -0500126 err := <-a.firstErr
127 a.firstErr <- err
Ian Cottrell877f9c42021-02-09 22:45:26 -0500128 return err
129}
130
131func (a *async) setError(err error) {
Bryan C. Mills5d35a752022-02-28 10:55:20 -0500132 storedErr := <-a.firstErr
Ian Cottrell877f9c42021-02-09 22:45:26 -0500133 if storedErr == nil {
134 storedErr = err
135 }
Bryan C. Mills5d35a752022-02-28 10:55:20 -0500136 a.firstErr <- storedErr
Ian Cottrell877f9c42021-02-09 22:45:26 -0500137}