package rpc import ( "bytes" "encoding/binary" "git.nspix.com/golang/micro/gateway/rpc/codec" "io" "net" ) type Request struct { codec codec.Codec conn net.Conn Method string Header map[string]string ContentLength int Sequence uint16 Body interface{} body []byte } func (r *Request) reset(seq uint16, conn net.Conn) { r.Sequence = seq r.conn = conn } //解码内容 func (r *Request) Decode(i interface{}) (err error) { return r.codec.Decode(r.body, i) } func (r *Request) RemoteAddr() net.Addr { if r.conn != nil { return r.conn.RemoteAddr() } return nil } func (r *Request) Bytes() []byte { buf := &bytes.Buffer{} if _, err := r.WriteTo(buf); err == nil { return buf.Bytes() } return nil } func (r *Request) WriteTo(w io.Writer) (n int64, err error) { var ( headerBuffer []byte bodyBuffer []byte m int headerLen int bodyLen int ) if r.Header == nil { r.Header = make(map[string]string) } r.Header["_METHOD"] = r.Method if headerBuffer, err = r.codec.Encode(r.Header); err != nil { return } if bodyBuffer, err = r.codec.Encode(r.Body); err != nil { return } headerLen = len(headerBuffer) bodyLen = len(bodyBuffer) if err = binary.Write(w, binary.LittleEndian, uint16(headerLen)); err != nil { return } n += 2 if err = binary.Write(w, binary.LittleEndian, uint16(bodyLen)); err != nil { return } n += 2 if m, err = w.Write(headerBuffer); err == nil { n += int64(m) } if m, err = w.Write(bodyBuffer); err == nil { n += int64(m) } return } func ReadRequest(b []byte) (req *Request, err error) { var ( p []byte headerBuffer []byte bodyBuffer []byte headerLen uint16 bodyLen uint16 ) req = &Request{ codec: codec.DefaultCodec, Header: make(map[string]string), } if b == nil || len(b) <= 4 { err = io.ErrShortBuffer return } headerLen = binary.LittleEndian.Uint16(b[0:2]) bodyLen = binary.LittleEndian.Uint16(b[2:4]) p = b[4:] if headerLen > 0 { if len(p) < int(headerLen) { err = io.ErrShortBuffer return } headerBuffer = p[:headerLen] if err = req.codec.Decode(headerBuffer, &req.Header); err != nil { return } req.Method = req.Header["_METHOD"] p = p[headerLen:] } if bodyLen > 0 { if len(p) < int(bodyLen) { err = io.ErrShortBuffer return } bodyBuffer = p[:bodyLen] req.body = make([]byte, bodyLen) copy(req.body[:], bodyBuffer[:]) req.ContentLength = int(bodyLen) } return } func NewRequest(method string, i interface{}) *Request { return &Request{ Method: method, Body: i, codec: codec.DefaultCodec, Header: make(map[string]string), } }