mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-08 10:10:27 +08:00
全面修订代码;完成 grpcSimple包;使用 tag选择编译quic 和 grpc
grpcSimple包的服务端和客户端现在都已完成,且兼容v2ray等内核。 grpcSimple包 简洁、高效,更加科学。暂不支持multiMode。 若 grpc_full 给出,则使用grpc包,否则默认使用 grpcSimple包。 若 noquic给出,则不使用 quic,否则 默认使用 quic。 修复 ws early 失效问题;
This commit is contained in:
@@ -1 +1,169 @@
|
||||
package grpcSimple
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Config
|
||||
|
||||
http2.Server
|
||||
|
||||
path string
|
||||
}
|
||||
|
||||
func (s *Server) GetPath() string {
|
||||
return s.ServiceName
|
||||
}
|
||||
|
||||
func (*Server) IsMux() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (*Server) IsSuper() bool {
|
||||
return false
|
||||
}
|
||||
func (s *Server) StartHandle(underlay net.Conn, newSubConnChan chan net.Conn) {
|
||||
go s.Server.ServeConn(underlay, &http2.ServeConnOpts{
|
||||
Handler: http.HandlerFunc(func(rw http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
//log.Println("request headers", rq.Header)
|
||||
|
||||
//TODO: support fallback
|
||||
|
||||
if rq.URL.Path != s.path {
|
||||
if ce := utils.CanLogWarn("grpc Server got wrong path"); ce != nil {
|
||||
ce.Write(zap.String("path", rq.URL.Path))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if ct := rq.Header.Get("Content-Type"); ct != "application/grpc" {
|
||||
if ce := utils.CanLogWarn("GRPC Server got wrong Content-Type"); ce != nil {
|
||||
ce.Write(zap.String("type", ct))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
//https://dzone.com/articles/learning-about-the-headers-used-for-grpc-over-http
|
||||
|
||||
headerMap := rw.Header()
|
||||
headerMap.Add("Content-Type", "application/grpc") //necessary
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
|
||||
cc := make(chan int)
|
||||
sc := &ServerConn{
|
||||
br: bufio.NewReader(rq.Body),
|
||||
Writer: rw,
|
||||
Closer: rq.Body,
|
||||
closeChan: cc,
|
||||
}
|
||||
|
||||
sc.timeouter = timeouter{
|
||||
closeFunc: func() {
|
||||
sc.Close()
|
||||
},
|
||||
}
|
||||
newSubConnChan <- sc
|
||||
<-cc //necessary
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
type ServerConn struct {
|
||||
io.Closer
|
||||
io.Writer
|
||||
|
||||
remain int
|
||||
br *bufio.Reader
|
||||
|
||||
once sync.Once
|
||||
closeChan chan int
|
||||
|
||||
timeouter
|
||||
}
|
||||
|
||||
func (g *ServerConn) Close() error {
|
||||
g.once.Do(func() {
|
||||
close(g.closeChan)
|
||||
g.Closer.Close()
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *ServerConn) Read(b []byte) (n int, err error) {
|
||||
|
||||
if g.remain > 0 {
|
||||
|
||||
size := g.remain
|
||||
if len(b) < size {
|
||||
size = len(b)
|
||||
}
|
||||
|
||||
n, err = io.ReadFull(g.br, b[:size])
|
||||
g.remain -= n
|
||||
return
|
||||
}
|
||||
|
||||
_, err = g.br.Discard(6)
|
||||
if err != nil {
|
||||
|
||||
return 0, err
|
||||
}
|
||||
|
||||
protobufPayloadLen, err := binary.ReadUvarint(g.br)
|
||||
if err != nil {
|
||||
return 0, ErrInvalidLength
|
||||
}
|
||||
|
||||
size := int(protobufPayloadLen)
|
||||
if len(b) < size {
|
||||
size = len(b)
|
||||
}
|
||||
|
||||
n, err = io.ReadFull(g.br, b[:size])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
remain := int(protobufPayloadLen) - n
|
||||
if remain > 0 {
|
||||
g.remain = remain
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (g *ServerConn) Write(b []byte) (n int, err error) {
|
||||
|
||||
protobufHeader := [binary.MaxVarintLen64 + 1]byte{0x0A}
|
||||
varuintSize := binary.PutUvarint(protobufHeader[1:], uint64(len(b)))
|
||||
grpcHeader := make([]byte, 5)
|
||||
grpcPayloadLen := uint32(varuintSize + 1 + len(b))
|
||||
binary.BigEndian.PutUint32(grpcHeader[1:5], grpcPayloadLen)
|
||||
|
||||
buf := utils.GetBuf()
|
||||
defer utils.PutBuf(buf)
|
||||
buf.Write(grpcHeader)
|
||||
buf.Write(protobufHeader[:varuintSize+1])
|
||||
buf.Write(b)
|
||||
|
||||
_, err = g.Writer.Write(buf.Bytes())
|
||||
|
||||
if err == nil {
|
||||
g.Writer.(http.Flusher).Flush() //necessary
|
||||
|
||||
}
|
||||
|
||||
return len(b), err
|
||||
}
|
||||
|
Reference in New Issue
Block a user