@@ -14,8 +14,6 @@ import (
14
14
"reflect"
15
15
"runtime"
16
16
"sync"
17
- "unicode"
18
- "unicode/utf8"
19
17
20
18
"github.com/go-delve/delve/pkg/logflags"
21
19
"github.com/go-delve/delve/pkg/version"
@@ -27,6 +25,8 @@ import (
27
25
"github.com/go-delve/delve/service/rpc2"
28
26
)
29
27
28
+ //go:generate go run ../../_scripts/gen-suitablemethods.go suitablemethods
29
+
30
30
// ServerImpl implements a JSON-RPC server that can switch between two
31
31
// versions of the API.
32
32
type ServerImpl struct {
@@ -62,8 +62,7 @@ type RPCServer struct {
62
62
}
63
63
64
64
type methodType struct {
65
- method reflect.Method
66
- Rcvr reflect.Value
65
+ method reflect.Value
67
66
ArgType reflect.Type
68
67
ReplyType reflect.Type
69
68
Synchronous bool
@@ -128,8 +127,10 @@ func (s *ServerImpl) Run() error {
128
127
s .methodMaps = make ([]map [string ]* methodType , 2 )
129
128
130
129
s .methodMaps [1 ] = map [string ]* methodType {}
131
- suitableMethods (s .s2 , s .methodMaps [1 ], s .log )
132
- suitableMethods (rpcServer , s .methodMaps [1 ], s .log )
130
+
131
+ suitableMethods2 (s .s2 , s .methodMaps [1 ])
132
+ suitableMethodsCommon (rpcServer , s .methodMaps [1 ])
133
+ finishMethodsMapInit (s .methodMaps [1 ])
133
134
134
135
go func () {
135
136
defer s .listener .Close ()
@@ -183,92 +184,15 @@ func (s *ServerImpl) serveConnectionDemux(c io.ReadWriteCloser) {
183
184
}
184
185
}
185
186
186
- // Precompute the reflect type for error. Can't use error directly
187
- // because Typeof takes an empty interface value. This is annoying.
188
- var typeOfError = reflect .TypeOf ((* error )(nil )).Elem ()
189
-
190
- // Is this an exported - upper case - name?
191
- func isExported (name string ) bool {
192
- ch , _ := utf8 .DecodeRuneInString (name )
193
- return unicode .IsUpper (ch )
194
- }
195
-
196
- // Is this type exported or a builtin?
197
- func isExportedOrBuiltinType (t reflect.Type ) bool {
198
- for t .Kind () == reflect .Ptr {
199
- t = t .Elem ()
200
- }
201
- // PkgPath will be non-empty even for an exported type,
202
- // so we need to check the type name as well.
203
- return isExported (t .Name ()) || t .PkgPath () == ""
204
- }
205
-
206
- // Fills methods map with the methods of receiver that should be made
207
- // available through the RPC interface.
208
- // These are all the public methods of rcvr that have one of those
209
- // two signatures:
210
- //
211
- // func (rcvr ReceiverType) Method(in InputType, out *ReplyType) error
212
- // func (rcvr ReceiverType) Method(in InputType, cb service.RPCCallback)
213
- func suitableMethods (rcvr interface {}, methods map [string ]* methodType , log logflags.Logger ) {
214
- typ := reflect .TypeOf (rcvr )
215
- rcvrv := reflect .ValueOf (rcvr )
216
- sname := reflect .Indirect (rcvrv ).Type ().Name ()
217
- if sname == "" {
218
- log .Debugf ("rpc.Register: no service name for type %s" , typ )
219
- return
220
- }
221
- for m := 0 ; m < typ .NumMethod (); m ++ {
222
- method := typ .Method (m )
223
- mname := method .Name
224
- mtype := method .Type
225
- // method must be exported
226
- if method .PkgPath != "" {
227
- continue
228
- }
229
- // Method needs three ins: (receive, *args, *reply) or (receiver, *args, *RPCCallback)
230
- if mtype .NumIn () != 3 {
231
- log .Warn ("method" , mname , "has wrong number of ins:" , mtype .NumIn ())
232
- continue
233
- }
234
- // First arg need not be a pointer.
235
- argType := mtype .In (1 )
236
- if ! isExportedOrBuiltinType (argType ) {
237
- log .Warn (mname , "argument type not exported:" , argType )
238
- continue
239
- }
240
-
241
- replyType := mtype .In (2 )
242
- synchronous := replyType .String () != "service.RPCCallback"
243
-
244
- if synchronous {
245
- // Second arg must be a pointer.
246
- if replyType .Kind () != reflect .Ptr {
247
- log .Warn ("method" , mname , "reply type not a pointer:" , replyType )
248
- continue
249
- }
250
- // Reply type must be exported.
251
- if ! isExportedOrBuiltinType (replyType ) {
252
- log .Warn ("method" , mname , "reply type not exported:" , replyType )
253
- continue
254
- }
255
-
256
- // Method needs one out.
257
- if mtype .NumOut () != 1 {
258
- log .Warn ("method" , mname , "has wrong number of outs:" , mtype .NumOut ())
259
- continue
260
- }
261
- // The return type of the method must be error.
262
- if returnType := mtype .Out (0 ); returnType != typeOfError {
263
- log .Warn ("method" , mname , "returns" , returnType .String (), "not error" )
264
- continue
265
- }
266
- } else if mtype .NumOut () != 0 {
267
- // Method needs zero outs.
268
- log .Warn ("method" , mname , "has wrong number of outs:" , mtype .NumOut ())
269
- continue
187
+ func finishMethodsMapInit (methods map [string ]* methodType ) {
188
+ for name , method := range methods {
189
+ mtype := method .method .Type ()
190
+ if mtype .NumIn () != 2 {
191
+ panic (fmt .Errorf ("wrong number of inputs for method %s (%d)" , name , mtype .NumIn ()))
270
192
}
271
- methods [sname + "." + mname ] = & methodType {method : method , ArgType : argType , ReplyType : replyType , Synchronous : synchronous , Rcvr : rcvrv }
193
+ method .ArgType = mtype .In (0 )
194
+ method .ReplyType = mtype .In (1 )
195
+ method .Synchronous = method .ReplyType .String () != "service.RPCCallback"
272
196
}
273
197
}
274
198
@@ -326,7 +250,7 @@ func (s *ServerImpl) serveJSONCodec(conn io.ReadWriteCloser) {
326
250
s .log .Debugf ("<- %s(%T%s)" , req .ServiceMethod , argv .Interface (), argvbytes )
327
251
}
328
252
replyv = reflect .New (mtype .ReplyType .Elem ())
329
- function := mtype .method . Func
253
+ function := mtype .method
330
254
var returnValues []reflect.Value
331
255
var errInter interface {}
332
256
func () {
@@ -335,7 +259,7 @@ func (s *ServerImpl) serveJSONCodec(conn io.ReadWriteCloser) {
335
259
errInter = newInternalError (ierr , 2 )
336
260
}
337
261
}()
338
- returnValues = function .Call ([]reflect.Value {mtype . Rcvr , argv , replyv })
262
+ returnValues = function .Call ([]reflect.Value {argv , replyv })
339
263
errInter = returnValues [0 ].Interface ()
340
264
}()
341
265
@@ -358,15 +282,15 @@ func (s *ServerImpl) serveJSONCodec(conn io.ReadWriteCloser) {
358
282
argvbytes , _ := json .Marshal (argv .Interface ())
359
283
s .log .Debugf ("(async %d) <- %s(%T%s)" , req .Seq , req .ServiceMethod , argv .Interface (), argvbytes )
360
284
}
361
- function := mtype .method . Func
285
+ function := mtype .method
362
286
ctl := & RPCCallback {s , sending , codec , req , make (chan struct {}), clientDisconnectChan }
363
287
go func () {
364
288
defer func () {
365
289
if ierr := recover (); ierr != nil {
366
290
ctl .Return (nil , newInternalError (ierr , 2 ))
367
291
}
368
292
}()
369
- function .Call ([]reflect.Value {mtype . Rcvr , argv , reflect .ValueOf (ctl )})
293
+ function .Call ([]reflect.Value {argv , reflect .ValueOf (ctl )})
370
294
}()
371
295
<- ctl .setupDone
372
296
}
0 commit comments