feat: implement server and client

This commit is contained in:
2022-04-23 01:24:17 +08:00
parent cf8fa335a6
commit 74ef998a9b
13 changed files with 631 additions and 120 deletions

View File

@ -5,14 +5,16 @@ import (
"io"
"reflect"
"sync"
"time"
"krwu.top/krpc.v1/codec"
)
type request struct {
h *codec.Header
argv reflect.Value
replyv reflect.Value
h *codec.Header
argv, replyv reflect.Value
mtype *methodType
svc *service
}
func (s *Server) readRequestHeader(cc codec.Codec) (*codec.Header, error) {
@ -32,16 +34,52 @@ func (s *Server) readRequest(cc codec.Codec) (*request, error) {
return nil, err
}
req := &request{h: h}
req.argv = reflect.New(reflect.TypeOf(""))
if err = cc.ReadBody(req.argv.Interface()); err != nil {
fmt.Println("rpc server: read argv err: ", err)
req.svc, req.mtype, err = s.findService(h.ServiceMethod)
if err != nil {
return req, err
}
req.argv = req.mtype.newArgv()
req.replyv = req.mtype.newReplyv()
argvi := req.argv.Interface()
if req.argv.Type().Kind() != reflect.Ptr {
argvi = req.argv.Addr().Interface()
}
if err = cc.ReadBody(argvi); err != nil {
fmt.Println("rpc: server read body error: ", err)
return req, err
}
return req, nil
}
func (s *Server) handleRequest(cc codec.Codec, req *request, sending *sync.Mutex, wg *sync.WaitGroup) {
func (s *Server) handleRequest(cc codec.Codec,
req *request, sending *sync.Mutex, wg *sync.WaitGroup, timeout time.Duration) {
defer wg.Done()
fmt.Println("rcp server: ", req.h, req.argv.Elem())
req.replyv = reflect.ValueOf(fmt.Sprintf("krpc resp %d", req.h.Seq))
s.sendResponse(cc, req.h, req.replyv.Interface(), sending)
called := make(chan struct{}, 1)
sent := make(chan struct{}, 1)
go func() {
err := req.svc.call(req.mtype, req.argv, req.replyv)
called <- struct{}{}
if err != nil {
req.h.Error = err.Error()
s.sendResponse(cc, req.h, invalidRequest, sending)
sent <- struct{}{}
return
}
s.sendResponse(cc, req.h, req.replyv.Interface(), sending)
sent <- struct{}{}
}()
if timeout == 0 {
<-called
<-sent
return
}
select {
case <-time.After(timeout):
req.h.Error = fmt.Sprintf("prc: server request handle timeout with %s", timeout)
s.sendResponse(cc, req.h, invalidRequest, sending)
case <-called:
<-sent
}
}