• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2019 The Go Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package jsonrpc2
16
17import (
18	"context"
19)
20
21// Handler is the interface used to hook into the message handling of an rpc
22// connection.
23type Handler interface {
24	// Deliver is invoked to handle incoming requests.
25	// If the request returns false from IsNotify then the Handler must eventually
26	// call Reply on the Conn with the supplied request.
27	// Handlers are called synchronously, they should pass the work off to a go
28	// routine if they are going to take a long time.
29	// If Deliver returns true all subsequent handlers will be invoked with
30	// delivered set to true, and should not attempt to deliver the message.
31	Deliver(ctx context.Context, r *Request, delivered bool) bool
32
33	// Cancel is invoked for cancelled outgoing requests.
34	// It is okay to use the connection to send notifications, but the context will
35	// be in the cancelled state, so you must do it with the background context
36	// instead.
37	// If Cancel returns true all subsequent handlers will be invoked with
38	// cancelled set to true, and should not attempt to cancel the message.
39	Cancel(ctx context.Context, conn *Conn, id ID, cancelled bool) bool
40
41	// Log is invoked for all messages flowing through a Conn.
42	// direction indicates if the message being received or sent
43	// id is the message id, if not set it was a notification
44	// elapsed is the time between a call being seen and the response, and is
45	// negative for anything that is not a response.
46	// method is the method name specified in the message
47	// payload is the parameters for a call or notification, and the result for a
48	// response
49
50	// Request is called near the start of processing any request.
51	Request(ctx context.Context, conn *Conn, direction Direction, r *WireRequest) context.Context
52	// Response is called near the start of processing any response.
53	Response(ctx context.Context, conn *Conn, direction Direction, r *WireResponse) context.Context
54	// Done is called when any request is fully processed.
55	// For calls, this means the response has also been processed, for notifies
56	// this is as soon as the message has been written to the stream.
57	// If err is set, it implies the request failed.
58	Done(ctx context.Context, err error)
59	// Read is called with a count each time some data is read from the stream.
60	// The read calls are delayed until after the data has been interpreted so
61	// that it can be attributed to a request/response.
62	Read(ctx context.Context, bytes int64) context.Context
63	// Wrote is called each time some data is written to the stream.
64	Wrote(ctx context.Context, bytes int64) context.Context
65	// Error is called with errors that cannot be delivered through the normal
66	// mechanisms, for instance a failure to process a notify cannot be delivered
67	// back to the other party.
68	Error(ctx context.Context, err error)
69}
70
71// Direction is used to indicate to a logger whether the logged message was being
72// sent or received.
73type Direction bool
74
75const (
76	// Send indicates the message is outgoing.
77	Send = Direction(true)
78	// Receive indicates the message is incoming.
79	Receive = Direction(false)
80)
81
82func (d Direction) String() string {
83	switch d {
84	case Send:
85		return "send"
86	case Receive:
87		return "receive"
88	default:
89		panic("unreachable")
90	}
91}
92
93type EmptyHandler struct{}
94
95func (EmptyHandler) Deliver(ctx context.Context, r *Request, delivered bool) bool {
96	return false
97}
98
99func (EmptyHandler) Cancel(ctx context.Context, conn *Conn, id ID, cancelled bool) bool {
100	return false
101}
102
103func (EmptyHandler) Request(ctx context.Context, conn *Conn, direction Direction, r *WireRequest) context.Context {
104	return ctx
105}
106
107func (EmptyHandler) Response(ctx context.Context, conn *Conn, direction Direction, r *WireResponse) context.Context {
108	return ctx
109}
110
111func (EmptyHandler) Done(ctx context.Context, err error) {
112}
113
114func (EmptyHandler) Read(ctx context.Context, bytes int64) context.Context {
115	return ctx
116}
117
118func (EmptyHandler) Wrote(ctx context.Context, bytes int64) context.Context {
119	return ctx
120}
121
122func (EmptyHandler) Error(ctx context.Context, err error) {}
123
124type defaultHandler struct{ EmptyHandler }
125
126func (defaultHandler) Deliver(ctx context.Context, r *Request, delivered bool) bool {
127	if delivered {
128		return false
129	}
130	if !r.IsNotify() {
131		r.Reply(ctx, nil, NewErrorf(CodeMethodNotFound, "method %q not found", r.Method))
132	}
133	return true
134}
135