ing
This commit is contained in:
		
							parent
							
								
									c6be50ff2c
								
							
						
					
					
						commit
						00dff62f10
					
				| @ -17,7 +17,8 @@ type CallState struct { | |||||||
| 	Error    error | 	Error    error | ||||||
| 	DoneChan chan *CallState | 	DoneChan chan *CallState | ||||||
| 
 | 
 | ||||||
| 	canceled uint32 | 	hasResponse bool | ||||||
|  | 	canceled    uint32 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (cs *CallState) done() { | func (cs *CallState) done() { | ||||||
|  | |||||||
| @ -24,9 +24,9 @@ type Client interface { | |||||||
| 	Connect() error | 	Connect() error | ||||||
| 	Close() | 	Close() | ||||||
| 
 | 
 | ||||||
| 	Notify(method string, args interface{}) error | 	Notify(method string, args ...interface{}) (err error) | ||||||
| 	Call(method string, args interface{}, result interface{}) error | 	Call(result interface{}, method string, args ...interface{}) error | ||||||
| 	CallTimeout(method string, args interface{}, result interface{}, timeout time.Duration) (err error) | 	CallTimeout(timeout time.Duration, result interface{}, method string, args ...interface{}) (err error) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type client struct { | type client struct { | ||||||
| @ -73,18 +73,28 @@ func (c *client) Close() { | |||||||
| 	c.stopChan = nil | 	c.stopChan = nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *client) Notify(method string, args interface{}) error { | func (c *client) Notify(method string, args ...interface{}) (err error) { | ||||||
| 	_, err := c.send(method, args, nil, false, true) |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (c *client) Call(method string, args interface{}, result interface{}) error { |  | ||||||
| 	return c.CallTimeout(method, args, result, c.ch.GetRequestTimeout()) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (c *client) CallTimeout(method string, args interface{}, result interface{}, timeout time.Duration) (err error) { |  | ||||||
| 	var cs *CallState | 	var cs *CallState | ||||||
| 	if cs, err = c.send(method, args, result, true, true); nil != err { | 	if cs, err = c.send(true, false, nil, method, args...); nil != err { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	select { | ||||||
|  | 	case <-cs.DoneChan: | ||||||
|  | 		err = cs.Error | ||||||
|  | 		releaseCallState(cs) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (c *client) Call(result interface{}, method string, args ...interface{}) error { | ||||||
|  | 	return c.CallTimeout(c.ch.GetRequestTimeout(), result, method, args...) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (c *client) CallTimeout(timeout time.Duration, result interface{}, method string, args ...interface{}) (err error) { | ||||||
|  | 	var cs *CallState | ||||||
|  | 	if cs, err = c.send(true, true, result, method, args...); nil != err { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -104,7 +114,7 @@ func (c *client) CallTimeout(method string, args interface{}, result interface{} | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *client) send(method string, args interface{}, result interface{}, hasResponse bool, usePool bool) (cs *CallState, err error) { | func (c *client) send(usePool bool, hasResponse bool, result interface{}, method string, args ...interface{}) (cs *CallState, err error) { | ||||||
| 	if !hasResponse { | 	if !hasResponse { | ||||||
| 		usePool = true | 		usePool = true | ||||||
| 	} | 	} | ||||||
| @ -115,13 +125,14 @@ func (c *client) send(method string, args interface{}, result interface{}, hasRe | |||||||
| 		cs = &CallState{} | 		cs = &CallState{} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	cs.hasResponse = hasResponse | ||||||
| 	cs.Method = method | 	cs.Method = method | ||||||
| 	cs.Args = args | 	cs.Args = args | ||||||
|  | 	cs.DoneChan = make(chan *CallState, 1) | ||||||
| 
 | 
 | ||||||
| 	if hasResponse { | 	if hasResponse { | ||||||
| 		cs.ID = c.ch.GetRequestID() | 		cs.ID = c.ch.GetRequestID() | ||||||
| 		cs.Result = result | 		cs.Result = result | ||||||
| 		cs.DoneChan = make(chan *CallState, 1) |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	select { | 	select { | ||||||
| @ -242,7 +253,7 @@ func (c *client) rpcWriter(stopChan <-chan struct{}, writerDone chan<- error) { | |||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if nil != cs.DoneChan { | 		if cs.hasResponse { | ||||||
| 			c.pendingRequestsLock.Lock() | 			c.pendingRequestsLock.Lock() | ||||||
| 			n := len(c.pendingRequests) | 			n := len(c.pendingRequests) | ||||||
| 			c.pendingRequests[cs.ID] = cs | 			c.pendingRequests[cs.ID] = cs | ||||||
| @ -256,8 +267,9 @@ func (c *client) rpcWriter(stopChan <-chan struct{}, writerDone chan<- error) { | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		err = c.ch.GetCodec().Write(c.conn, cs.Method, cs.Args, cs.ID) | 		err = c.ch.GetCodec().Write(c.conn, cs.Method, cs.Args, cs.ID) | ||||||
| 		if nil == cs.DoneChan { | 		if !cs.hasResponse { | ||||||
| 			releaseCallState(cs) | 			cs.Error = err | ||||||
|  | 			cs.done() | ||||||
| 		} | 		} | ||||||
| 		if nil != err { | 		if nil != err { | ||||||
| 			err = fmt.Errorf("Client: Cannot send request to wire: [%s]", err) | 			err = fmt.Errorf("Client: Cannot send request to wire: [%s]", err) | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								gateway/gateway.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/gateway.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | package gateway | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"git.loafle.net/commons_go/server" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func New(sh ServerHandler) server.Server { | ||||||
|  | 	s := server.New(sh) | ||||||
|  | 
 | ||||||
|  | 	return s | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								gateway/rpc_gateway_handler.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								gateway/rpc_gateway_handler.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | package gateway | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"git.loafle.net/commons_go/rpc/protocol" | ||||||
|  | 	"git.loafle.net/commons_go/rpc/server" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type RPCGetewayHandler interface { | ||||||
|  | 	server.RPCServerHandler | ||||||
|  | 	Handle(codecReq protocol.ServerCodecRequest) (interface{}, error) | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								gateway/rpc_gateway_handlers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								gateway/rpc_gateway_handlers.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | package gateway | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  | 
 | ||||||
|  | 	"git.loafle.net/commons_go/rpc/protocol" | ||||||
|  | 	"git.loafle.net/commons_go/rpc/server" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type RPCGetewayHandlers struct { | ||||||
|  | 	server.RPCServerHandlers | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (rpcGH *RPCGetewayHandlers) Handle(codecReq protocol.ServerCodecRequest) (result interface{}, err error) { | ||||||
|  | 	return nil, errors.New("RPC Gateway: Handler method[Handle] is not implement") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (rpcGH *RPCGetewayHandlers) Validate() { | ||||||
|  | 	rpcGH.RPCServerHandlers.Validate() | ||||||
|  | } | ||||||
							
								
								
									
										67
									
								
								gateway/server_handlers.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								gateway/server_handlers.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | |||||||
|  | package gateway | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 	"net" | ||||||
|  | 
 | ||||||
|  | 	"git.loafle.net/commons_go/server" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type ServerHandlers struct { | ||||||
|  | 	server.ServerHandlers | ||||||
|  | 
 | ||||||
|  | 	RPCGetewayHandler RPCGetewayHandler | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (sh *ServerHandlers) Handle(conn net.Conn, stopChan <-chan struct{}, doneChan chan<- struct{}) { | ||||||
|  | 	contentType := sh.RPCGetewayHandler.GetContentType(conn) | ||||||
|  | 	codec, err := sh.RPCGetewayHandler.GetCodec(contentType) | ||||||
|  | 	if nil != err { | ||||||
|  | 		log.Printf("RPC Handle: %v", err) | ||||||
|  | 		doneChan <- struct{}{} | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for { | ||||||
|  | 		sh.RPCGetewayHandler.OnPreRead(conn) | ||||||
|  | 		// Create a new codec request. | ||||||
|  | 		codecReq, errNew := codec.NewRequest(conn) | ||||||
|  | 		if nil != errNew { | ||||||
|  | 			if sh.IsClientDisconnect(errNew) { | ||||||
|  | 				doneChan <- struct{}{} | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			log.Printf("RPC Handle: %v", errNew) | ||||||
|  | 			doneChan <- struct{}{} | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		sh.RPCGetewayHandler.OnPostRead(conn) | ||||||
|  | 
 | ||||||
|  | 		result, err := sh.RPCGetewayHandler.Handle(codecReq) | ||||||
|  | 
 | ||||||
|  | 		if nil != err { | ||||||
|  | 			sh.RPCGetewayHandler.OnPreWriteError(conn, err) | ||||||
|  | 			codecReq.WriteError(conn, 400, err) | ||||||
|  | 			sh.RPCGetewayHandler.OnPostWriteError(conn, err) | ||||||
|  | 		} else { | ||||||
|  | 			sh.RPCGetewayHandler.OnPreWriteResult(conn, result) | ||||||
|  | 			codecReq.WriteResponse(conn, result) | ||||||
|  | 			sh.RPCGetewayHandler.OnPostWriteResult(conn, result) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		select { | ||||||
|  | 		case <-stopChan: | ||||||
|  | 			return | ||||||
|  | 		default: | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (sh *ServerHandlers) Validate() { | ||||||
|  | 	sh.ServerHandlers.Validate() | ||||||
|  | 
 | ||||||
|  | 	if nil == sh.RPCGetewayHandler { | ||||||
|  | 		panic("RPCGetewayHandler must be specified.") | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -47,22 +47,15 @@ func (ccn *ClientCodecNotify) Method() string { | |||||||
| 	return ccn.notify.Method | 	return ccn.notify.Method | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ccn *ClientCodecNotify) ReadParams(args interface{}) error { | func (ccn *ClientCodecNotify) ReadParams(args []interface{}) error { | ||||||
| 	if ccn.err == nil && ccn.notify.Params != nil { | 	if ccn.err == nil && ccn.notify.Params != nil { | ||||||
| 		// Note: if scr.request.Params is nil it's not an error, it's an optional member. | 		// Note: if scr.request.Params is nil it's not an error, it's an optional member. | ||||||
| 		// JSON params structured object. Unmarshal to the args object. | 		// JSON params structured object. Unmarshal to the args object. | ||||||
| 		if err := json.Unmarshal(*ccn.notify.Params, args); err != nil { | 		if err := json.Unmarshal(*ccn.notify.Params, args); err != nil { | ||||||
| 			// Clearly JSON params is not a structured object, | 			ccn.err = &Error{ | ||||||
| 			// fallback and attempt an unmarshal with JSON params as | 				Code:    E_INVALID_REQ, | ||||||
| 			// array value and RPC params is struct. Unmarshal into | 				Message: err.Error(), | ||||||
| 			// array containing the request struct. | 				Data:    ccn.notify.Params, | ||||||
| 			params := [1]interface{}{args} |  | ||||||
| 			if err = json.Unmarshal(*ccn.notify.Params, ¶ms); err != nil { |  | ||||||
| 				ccn.err = &Error{ |  | ||||||
| 					Code:    E_INVALID_REQ, |  | ||||||
| 					Message: err.Error(), |  | ||||||
| 					Data:    ccn.notify.Params, |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -160,7 +160,7 @@ func (scr *ServerCodecRequest) Method() string { | |||||||
| // absence of expected names MAY result in an error being | // absence of expected names MAY result in an error being | ||||||
| // generated. The names MUST match exactly, including | // generated. The names MUST match exactly, including | ||||||
| // case, to the method's expected parameters. | // case, to the method's expected parameters. | ||||||
| func (scr *ServerCodecRequest) ReadParams(args interface{}) error { | func (scr *ServerCodecRequest) ReadParams(args []interface{}) error { | ||||||
| 	if scr.err == nil && scr.request.Params != nil { | 	if scr.err == nil && scr.request.Params != nil { | ||||||
| 		// Note: if scr.request.Params is nil it's not an error, it's an optional member. | 		// Note: if scr.request.Params is nil it's not an error, it's an optional member. | ||||||
| 		// JSON params structured object. Unmarshal to the args object. | 		// JSON params structured object. Unmarshal to the args object. | ||||||
| @ -169,13 +169,10 @@ func (scr *ServerCodecRequest) ReadParams(args interface{}) error { | |||||||
| 			// fallback and attempt an unmarshal with JSON params as | 			// fallback and attempt an unmarshal with JSON params as | ||||||
| 			// array value and RPC params is struct. Unmarshal into | 			// array value and RPC params is struct. Unmarshal into | ||||||
| 			// array containing the request struct. | 			// array containing the request struct. | ||||||
| 			params := [1]interface{}{args} | 			scr.err = &Error{ | ||||||
| 			if err = json.Unmarshal(*scr.request.Params, ¶ms); err != nil { | 				Code:    E_INVALID_REQ, | ||||||
| 				scr.err = &Error{ | 				Message: err.Error(), | ||||||
| 					Code:    E_INVALID_REQ, | 				Data:    scr.request.Params, | ||||||
| 					Message: err.Error(), |  | ||||||
| 					Data:    scr.request.Params, |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -8,6 +8,6 @@ type RegistryCodec interface { | |||||||
| 	// Reads the request and returns the RPC method name. | 	// Reads the request and returns the RPC method name. | ||||||
| 	Method() string | 	Method() string | ||||||
| 	// Reads the request filling the RPC method args. | 	// Reads the request filling the RPC method args. | ||||||
| 	ReadParams(interface{}) error | 	ReadParams([]interface{}) error | ||||||
| 	Complete() | 	Complete() | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										41
									
								
								registry.go
									
									
									
									
									
								
							
							
						
						
									
										41
									
								
								registry.go
									
									
									
									
									
								
							| @ -75,28 +75,31 @@ func (rr *rpcRegistry) Invoke(codec protocol.RegistryCodec) (result interface{}, | |||||||
| 		return nil, errGet | 		return nil, errGet | ||||||
| 	} | 	} | ||||||
| 	// Decode the args. | 	// Decode the args. | ||||||
| 	args := reflect.New(methodSpec.argsType) | 
 | ||||||
| 	if errRead := codec.ReadParams(args.Interface()); errRead != nil { | 	var in []reflect.Value | ||||||
| 		return nil, errRead | 	paramValues, paramInstances := methodSpec.getParams() | ||||||
|  | 	if nil != paramValues { | ||||||
|  | 		in = make([]reflect.Value, len(paramValues)+1) | ||||||
|  | 		if errRead := codec.ReadParams(paramInstances); errRead != nil { | ||||||
|  | 			return nil, errRead | ||||||
|  | 		} | ||||||
|  | 		for indexI := 0; indexI < len(paramValues); indexI++ { | ||||||
|  | 			in[indexI+1] = paramValues[indexI] | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		in = make([]reflect.Value, 1) | ||||||
| 	} | 	} | ||||||
|  | 	in[0] = serviceSpec.rcvr | ||||||
|  | 
 | ||||||
| 	// Call the service method. | 	// Call the service method. | ||||||
| 	reply := reflect.New(methodSpec.replyType) | 	returnValues := methodSpec.method.Func.Call(in) | ||||||
| 	errValue := methodSpec.method.Func.Call([]reflect.Value{ |  | ||||||
| 		serviceSpec.rcvr, |  | ||||||
| 		args, |  | ||||||
| 		reply, |  | ||||||
| 	}) |  | ||||||
| 
 | 
 | ||||||
| 	// Cast the result to error if needed. | 	if nil != methodSpec.returnType { | ||||||
| 	var errResult error | 		result = returnValues[0].Interface() | ||||||
| 	errInter := errValue[0].Interface() | 		err = returnValues[1].Interface().(error) | ||||||
| 	if errInter != nil { | 	} else { | ||||||
| 		errResult = errInter.(error) | 		err = returnValues[0].Interface().(error) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if errResult != nil { | 	return | ||||||
| 		return nil, errResult |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return reply.Interface(), nil |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -19,6 +19,6 @@ type RPCServerHandler interface { | |||||||
| 	OnPreWriteError(w io.Writer, err error) | 	OnPreWriteError(w io.Writer, err error) | ||||||
| 	OnPostWriteError(w io.Writer, err error) | 	OnPostWriteError(w io.Writer, err error) | ||||||
| 
 | 
 | ||||||
| 	getCodec(contentType string) (protocol.ServerCodec, error) | 	GetCodec(contentType string) (protocol.ServerCodec, error) | ||||||
| 	invoke(codec protocol.RegistryCodec) (result interface{}, err error) | 	invoke(codec protocol.RegistryCodec) (result interface{}, err error) | ||||||
| } | } | ||||||
|  | |||||||
| @ -60,7 +60,7 @@ func (rpcSH *RPCServerHandlers) Validate() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (rpcSH *RPCServerHandlers) getCodec(contentType string) (protocol.ServerCodec, error) { | func (rpcSH *RPCServerHandlers) GetCodec(contentType string) (protocol.ServerCodec, error) { | ||||||
| 	var codec protocol.ServerCodec | 	var codec protocol.ServerCodec | ||||||
| 	if contentType == "" && len(rpcSH.codecs) == 1 { | 	if contentType == "" && len(rpcSH.codecs) == 1 { | ||||||
| 		// If Content-Type is not set and only one codec has been registered, | 		// If Content-Type is not set and only one codec has been registered, | ||||||
|  | |||||||
| @ -15,7 +15,7 @@ type ServerHandlers struct { | |||||||
| 
 | 
 | ||||||
| func (sh *ServerHandlers) Handle(conn net.Conn, stopChan <-chan struct{}, doneChan chan<- struct{}) { | func (sh *ServerHandlers) Handle(conn net.Conn, stopChan <-chan struct{}, doneChan chan<- struct{}) { | ||||||
| 	contentType := sh.RPCServerHandler.GetContentType(conn) | 	contentType := sh.RPCServerHandler.GetContentType(conn) | ||||||
| 	codec, err := sh.RPCServerHandler.getCodec(contentType) | 	codec, err := sh.RPCServerHandler.GetCodec(contentType) | ||||||
| 	if nil != err { | 	if nil != err { | ||||||
| 		log.Printf("RPC Handle: %v", err) | 		log.Printf("RPC Handle: %v", err) | ||||||
| 		doneChan <- struct{}{} | 		doneChan <- struct{}{} | ||||||
|  | |||||||
| @ -26,11 +26,27 @@ type service struct { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type serviceMethod struct { | type serviceMethod struct { | ||||||
| 	method    reflect.Method // receiver method | 	method     reflect.Method // receiver method | ||||||
| 	argsType  reflect.Type   // type of the request argument | 	paramTypes []reflect.Type // type of the request argument | ||||||
| 	replyType reflect.Type   // type of the response argument | 	returnType reflect.Type   // type of the response argument | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (sm *serviceMethod) getParams() (values []reflect.Value, instances []interface{}) { | ||||||
|  | 	if nil == sm.paramTypes || 0 == len(sm.paramTypes) { | ||||||
|  | 		return nil, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	pCount := len(sm.paramTypes) | ||||||
|  | 	values = make([]reflect.Value, pCount) | ||||||
|  | 	instances = make([]interface{}, pCount) | ||||||
|  | 
 | ||||||
|  | 	for indexI := 0; indexI < pCount; indexI++ { | ||||||
|  | 		values[indexI] = reflect.New(sm.paramTypes[indexI]) | ||||||
|  | 		instances[indexI] = values[indexI].Interface() | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| // ---------------------------------------------------------------------------- | // ---------------------------------------------------------------------------- | ||||||
| // serviceMap | // serviceMap | ||||||
| @ -63,6 +79,7 @@ func (m *serviceMap) register(rcvr interface{}, name string) error { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// Setup methods. | 	// Setup methods. | ||||||
|  | Loop: | ||||||
| 	for i := 0; i < s.rcvrType.NumMethod(); i++ { | 	for i := 0; i < s.rcvrType.NumMethod(); i++ { | ||||||
| 		method := s.rcvrType.Method(i) | 		method := s.rcvrType.Method(i) | ||||||
| 		mtype := method.Type | 		mtype := method.Type | ||||||
| @ -70,37 +87,48 @@ func (m *serviceMap) register(rcvr interface{}, name string) error { | |||||||
| 		if method.PkgPath != "" { | 		if method.PkgPath != "" { | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 		// Method needs four ins: receiver, *args, *reply. | 
 | ||||||
| 		if mtype.NumIn() != 3 { | 		var paramTypes []reflect.Type | ||||||
| 			continue | 
 | ||||||
|  | 		mCount := mtype.NumIn() | ||||||
|  | 		if 0 < mCount { | ||||||
|  | 			paramTypes = make([]reflect.Type, mCount) | ||||||
|  | 			for indexI := 0; indexI < mCount; indexI++ { | ||||||
|  | 				param := mtype.In(indexI) | ||||||
|  | 				if !isExportedOrBuiltin(param) { | ||||||
|  | 					continue Loop | ||||||
|  | 				} | ||||||
|  | 				paramTypes[indexI] = param.Elem() | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		// First argument must be a pointer and must be exported. | 
 | ||||||
| 		args := mtype.In(1) | 		var returnType reflect.Type | ||||||
| 		if args.Kind() != reflect.Ptr || !isExportedOrBuiltin(args) { | 		switch mtype.NumOut() { | ||||||
| 			continue | 		case 1: | ||||||
| 		} | 			if returnType := mtype.Out(0); returnType != typeOfError { | ||||||
| 		// Second argument must be a pointer and must be exported. | 				continue Loop | ||||||
| 		reply := mtype.In(2) | 			} | ||||||
| 		if reply.Kind() != reflect.Ptr || !isExportedOrBuiltin(reply) { | 		case 2: | ||||||
|  | 			if returnType := mtype.Out(0); !isExportedOrBuiltin(returnType) { | ||||||
|  | 				continue Loop | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if returnType := mtype.Out(1); returnType != typeOfError { | ||||||
|  | 				continue Loop | ||||||
|  | 			} | ||||||
|  | 			returnType = mtype.Out(1).Elem() | ||||||
|  | 		default: | ||||||
| 			continue | 			continue | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// Method needs one out: error. |  | ||||||
| 		if mtype.NumOut() != 1 { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		if returnType := mtype.Out(0); returnType != typeOfError { |  | ||||||
| 			continue |  | ||||||
| 		} |  | ||||||
| 		s.methods[method.Name] = &serviceMethod{ | 		s.methods[method.Name] = &serviceMethod{ | ||||||
| 			method:    method, | 			method:     method, | ||||||
| 			argsType:  args.Elem(), | 			paramTypes: paramTypes, | ||||||
| 			replyType: reply.Elem(), | 			returnType: returnType, | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if len(s.methods) == 0 { | 	if len(s.methods) == 0 { | ||||||
| 		return fmt.Errorf("rpc: %q has no exported methods of suitable type", | 		return fmt.Errorf("rpc: %q has no exported methods of suitable type", s.name) | ||||||
| 			s.name) |  | ||||||
| 	} | 	} | ||||||
| 	// Add to the map. | 	// Add to the map. | ||||||
| 	m.mutex.Lock() | 	m.mutex.Lock() | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user