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