fix http2 bugs
This commit is contained in:
parent
a1506e7b3b
commit
124bfc42ea
41
chain.go
41
chain.go
@ -75,14 +75,14 @@ func (c *ProxyChain) TryEnableHttp2() {
|
|||||||
|
|
||||||
// HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present.
|
// HTTP2 restrict: HTTP2 will be enabled when at least one HTTP2 proxy node is present.
|
||||||
for i, node := range c.nodes {
|
for i, node := range c.nodes {
|
||||||
if node.Transport == "http2" {
|
if node.Transport == "http2" || node.Protocol == "http2" {
|
||||||
glog.V(LINFO).Infoln("HTTP2 enabled")
|
glog.V(LINFO).Infoln("HTTP2 is enabled")
|
||||||
cfg := &tls.Config{
|
cfg := &tls.Config{
|
||||||
InsecureSkipVerify: node.insecureSkipVerify(),
|
InsecureSkipVerify: node.insecureSkipVerify(),
|
||||||
ServerName: node.serverName,
|
ServerName: node.serverName,
|
||||||
}
|
}
|
||||||
c.initHttp2Client(node.Addr, cfg, c.nodes[:i]...)
|
|
||||||
c.http2NodeIndex = i
|
c.http2NodeIndex = i
|
||||||
|
c.initHttp2Client(cfg, c.nodes[:i]...)
|
||||||
break // shortest chain for HTTP2
|
break // shortest chain for HTTP2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -92,12 +92,17 @@ func (c *ProxyChain) Http2Enabled() bool {
|
|||||||
return c.http2Enabled
|
return c.http2Enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ProxyChain) initHttp2Client(addr string, config *tls.Config, nodes ...ProxyNode) {
|
func (c *ProxyChain) initHttp2Client(config *tls.Config, nodes ...ProxyNode) {
|
||||||
|
if c.http2NodeIndex < 0 || c.http2NodeIndex >= len(c.nodes) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
http2Node := c.nodes[c.http2NodeIndex]
|
||||||
|
|
||||||
tr := http2.Transport{
|
tr := http2.Transport{
|
||||||
TLSClientConfig: config,
|
TLSClientConfig: config,
|
||||||
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
|
DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
|
||||||
// replace the default dialer with our proxy chain.
|
// replace the default dialer with our proxy chain.
|
||||||
conn, err := c.dialWithNodes(addr, nodes...)
|
conn, err := c.dialWithNodes(false, http2Node.Addr, nodes...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
@ -114,7 +119,7 @@ func (c *ProxyChain) Dial(addr string) (net.Conn, error) {
|
|||||||
if !strings.Contains(addr, ":") {
|
if !strings.Contains(addr, ":") {
|
||||||
addr += ":80"
|
addr += ":80"
|
||||||
}
|
}
|
||||||
return c.dialWithNodes(addr, c.nodes...)
|
return c.dialWithNodes(true, addr, c.nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetConn initializes a proxy chain connection,
|
// GetConn initializes a proxy chain connection,
|
||||||
@ -135,8 +140,8 @@ func (c *ProxyChain) GetConn() (net.Conn, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
http2Node := c.nodes[c.http2NodeIndex]
|
http2Node := c.nodes[c.http2NodeIndex]
|
||||||
if http2Node.Protocol == "" {
|
if http2Node.Protocol == "http2" {
|
||||||
http2Node.Protocol = "socks5" // assume it as socks5 protocol
|
http2Node.Protocol = "socks5" // assume it as socks5 protocol, so we can do much more things.
|
||||||
}
|
}
|
||||||
pc := NewProxyConn(conn, http2Node)
|
pc := NewProxyConn(conn, http2Node)
|
||||||
if err := pc.Handshake(); err != nil {
|
if err := pc.Handshake(); err != nil {
|
||||||
@ -146,21 +151,21 @@ func (c *ProxyChain) GetConn() (net.Conn, error) {
|
|||||||
return pc, nil
|
return pc, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c.travelNodes(nodes...)
|
return c.travelNodes(true, nodes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ProxyChain) dialWithNodes(addr string, nodes ...ProxyNode) (conn net.Conn, err error) {
|
func (c *ProxyChain) dialWithNodes(withHttp2 bool, addr string, nodes ...ProxyNode) (conn net.Conn, err error) {
|
||||||
if len(nodes) == 0 {
|
if len(nodes) == 0 {
|
||||||
return net.DialTimeout("tcp", addr, DialTimeout)
|
return net.DialTimeout("tcp", addr, DialTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Http2Enabled() {
|
if withHttp2 && c.Http2Enabled() {
|
||||||
nodes = nodes[c.http2NodeIndex+1:]
|
nodes = nodes[c.http2NodeIndex+1:]
|
||||||
if len(nodes) == 0 {
|
if len(nodes) == 0 {
|
||||||
return c.http2Connect(addr)
|
return c.http2Connect(addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pc, err := c.travelNodes(nodes...)
|
pc, err := c.travelNodes(withHttp2, nodes...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -172,7 +177,7 @@ func (c *ProxyChain) dialWithNodes(addr string, nodes ...ProxyNode) (conn net.Co
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ProxyChain) travelNodes(nodes ...ProxyNode) (conn *ProxyConn, err error) {
|
func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *ProxyConn, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil && conn != nil {
|
if err != nil && conn != nil {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
@ -183,7 +188,7 @@ func (c *ProxyChain) travelNodes(nodes ...ProxyNode) (conn *ProxyConn, err error
|
|||||||
var cc net.Conn
|
var cc net.Conn
|
||||||
node := nodes[0]
|
node := nodes[0]
|
||||||
|
|
||||||
if c.Http2Enabled() {
|
if withHttp2 && c.Http2Enabled() {
|
||||||
cc, err = c.http2Connect(node.Addr)
|
cc, err = c.http2Connect(node.Addr)
|
||||||
} else {
|
} else {
|
||||||
cc, err = net.DialTimeout("tcp", node.Addr, DialTimeout)
|
cc, err = net.DialTimeout("tcp", node.Addr, DialTimeout)
|
||||||
@ -214,7 +219,7 @@ func (c *ProxyChain) travelNodes(nodes ...ProxyNode) (conn *ProxyConn, err error
|
|||||||
// Initialize an HTTP2 transport if HTTP2 is enabled.
|
// Initialize an HTTP2 transport if HTTP2 is enabled.
|
||||||
func (c *ProxyChain) getHttp2Conn(header http.Header) (net.Conn, error) {
|
func (c *ProxyChain) getHttp2Conn(header http.Header) (net.Conn, error) {
|
||||||
if !c.Http2Enabled() {
|
if !c.Http2Enabled() {
|
||||||
return nil, errors.New("HTTP2 not enabled")
|
return nil, errors.New("HTTP2 is not enabled")
|
||||||
}
|
}
|
||||||
http2Node := c.nodes[c.http2NodeIndex]
|
http2Node := c.nodes[c.http2NodeIndex]
|
||||||
pr, pw := io.Pipe()
|
pr, pw := io.Pipe()
|
||||||
@ -242,6 +247,10 @@ func (c *ProxyChain) getHttp2Conn(header http.Header) (net.Conn, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if glog.V(LDEBUG) {
|
||||||
|
dump, _ := httputil.DumpResponse(resp, false)
|
||||||
|
glog.Infoln(string(dump))
|
||||||
|
}
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
return nil, errors.New(resp.Status)
|
return nil, errors.New(resp.Status)
|
||||||
@ -254,7 +263,7 @@ func (c *ProxyChain) getHttp2Conn(header http.Header) (net.Conn, error) {
|
|||||||
// Use HTTP2 as transport to connect target addr
|
// Use HTTP2 as transport to connect target addr
|
||||||
func (c *ProxyChain) http2Connect(addr string) (net.Conn, error) {
|
func (c *ProxyChain) http2Connect(addr string) (net.Conn, error) {
|
||||||
if !c.Http2Enabled() {
|
if !c.Http2Enabled() {
|
||||||
return nil, errors.New("HTTP2 not enabled")
|
return nil, errors.New("HTTP2 is not enabled")
|
||||||
}
|
}
|
||||||
http2Node := c.nodes[c.http2NodeIndex]
|
http2Node := c.nodes[c.http2NodeIndex]
|
||||||
|
|
||||||
|
2
conn.go
2
conn.go
@ -119,7 +119,7 @@ func (c *ProxyConn) handshake() error {
|
|||||||
}
|
}
|
||||||
c.conn = &shadowConn{conn: shadowsocks.NewConn(c.conn, cipher)}
|
c.conn = &shadowConn{conn: shadowsocks.NewConn(c.conn, cipher)}
|
||||||
}
|
}
|
||||||
case "http":
|
case "http", "http2":
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
2
gost.go
2
gost.go
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Version = "2.2-rc1"
|
Version = "2.2-rc2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Log level for glog
|
// Log level for glog
|
||||||
|
12
http.go
12
http.go
@ -343,9 +343,19 @@ type flushWriter struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fw flushWriter) Write(p []byte) (n int, err error) {
|
func (fw flushWriter) Write(p []byte) (n int, err error) {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
if s, ok := r.(string); ok {
|
||||||
|
err = errors.New(s)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = r.(error)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
n, err = fw.w.Write(p)
|
n, err = fw.w.Write(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(LWARNING).Infoln("flush writer:", err)
|
// glog.V(LWARNING).Infoln("flush writer:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if f, ok := fw.w.(http.Flusher); ok {
|
if f, ok := fw.w.(http.Flusher); ok {
|
||||||
|
Loading…
Reference in New Issue
Block a user