Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
G
gost
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
gost
Commits
333291e9
Commit
333291e9
authored
Feb 05, 2017
by
rui.zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#76 support pure HTTP tunnel(PHT)
parent
72d8a598
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
694 additions
and
15 deletions
+694
-15
chain.go
chain.go
+11
-2
cmd/gost/vendor/github.com/ginuerzh/gost/chain.go
cmd/gost/vendor/github.com/ginuerzh/gost/chain.go
+11
-2
cmd/gost/vendor/github.com/ginuerzh/gost/http.go
cmd/gost/vendor/github.com/ginuerzh/gost/http.go
+29
-2
cmd/gost/vendor/github.com/ginuerzh/gost/node.go
cmd/gost/vendor/github.com/ginuerzh/gost/node.go
+1
-1
cmd/gost/vendor/github.com/ginuerzh/gost/server.go
cmd/gost/vendor/github.com/ginuerzh/gost/server.go
+3
-1
cmd/gost/vendor/github.com/ginuerzh/pht/LICENSE
cmd/gost/vendor/github.com/ginuerzh/pht/LICENSE
+21
-0
cmd/gost/vendor/github.com/ginuerzh/pht/README.md
cmd/gost/vendor/github.com/ginuerzh/pht/README.md
+2
-0
cmd/gost/vendor/github.com/ginuerzh/pht/client.go
cmd/gost/vendor/github.com/ginuerzh/pht/client.go
+162
-0
cmd/gost/vendor/github.com/ginuerzh/pht/conn.go
cmd/gost/vendor/github.com/ginuerzh/pht/conn.go
+133
-0
cmd/gost/vendor/github.com/ginuerzh/pht/server.go
cmd/gost/vendor/github.com/ginuerzh/pht/server.go
+199
-0
cmd/gost/vendor/github.com/ginuerzh/pht/session.go
cmd/gost/vendor/github.com/ginuerzh/pht/session.go
+80
-0
cmd/gost/vendor/vendor.json
cmd/gost/vendor/vendor.json
+9
-3
http.go
http.go
+29
-2
node.go
node.go
+1
-1
server.go
server.go
+3
-1
No files found.
chain.go
View file @
333291e9
...
...
@@ -5,6 +5,7 @@ import (
"crypto/tls"
"encoding/base64"
"errors"
"github.com/ginuerzh/pht"
"github.com/golang/glog"
"golang.org/x/net/http2"
"io"
...
...
@@ -29,6 +30,7 @@ type ProxyChain struct {
kcpConfig
*
KCPConfig
kcpSession
*
KCPSession
kcpMutex
sync
.
Mutex
phttpClient
*
pht
.
Client
}
func
NewProxyChain
(
nodes
...
ProxyNode
)
*
ProxyChain
{
...
...
@@ -96,8 +98,8 @@ func (c *ProxyChain) Init() {
}
for
i
,
node
:=
range
c
.
nodes
{
if
node
.
Transport
==
"kcp"
&&
i
>
0
{
glog
.
Fatal
(
"KCP must be the first node in the proxy chain"
)
if
(
node
.
Transport
==
"kcp"
||
node
.
Transport
==
"pht"
||
node
.
Transport
==
"quic"
)
&&
i
>
0
{
glog
.
Fatal
(
"KCP
/PHT/QUIC
must be the first node in the proxy chain"
)
}
}
...
...
@@ -118,6 +120,11 @@ func (c *ProxyChain) Init() {
c
.
kcpConfig
=
config
return
}
if
c
.
nodes
[
0
]
.
Transport
==
"pht"
{
glog
.
V
(
LINFO
)
.
Infoln
(
"Pure HTTP mode is enabled"
)
c
.
phttpClient
=
pht
.
NewClient
(
c
.
nodes
[
0
]
.
Addr
,
c
.
nodes
[
0
]
.
Get
(
"key"
))
}
}
func
(
c
*
ProxyChain
)
KCPEnabled
()
bool
{
...
...
@@ -269,6 +276,8 @@ func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *Prox
cc
,
err
=
c
.
http2Connect
(
node
.
Addr
)
}
else
if
node
.
Transport
==
"kcp"
{
cc
,
err
=
c
.
getKCPConn
()
}
else
if
node
.
Transport
==
"pht"
{
cc
,
err
=
c
.
phttpClient
.
Dial
()
}
else
{
cc
,
err
=
net
.
DialTimeout
(
"tcp"
,
node
.
Addr
,
DialTimeout
)
}
...
...
cmd/gost/vendor/github.com/ginuerzh/gost/chain.go
View file @
333291e9
...
...
@@ -5,6 +5,7 @@ import (
"crypto/tls"
"encoding/base64"
"errors"
"github.com/ginuerzh/pht"
"github.com/golang/glog"
"golang.org/x/net/http2"
"io"
...
...
@@ -29,6 +30,7 @@ type ProxyChain struct {
kcpConfig
*
KCPConfig
kcpSession
*
KCPSession
kcpMutex
sync
.
Mutex
phttpClient
*
pht
.
Client
}
func
NewProxyChain
(
nodes
...
ProxyNode
)
*
ProxyChain
{
...
...
@@ -96,8 +98,8 @@ func (c *ProxyChain) Init() {
}
for
i
,
node
:=
range
c
.
nodes
{
if
node
.
Transport
==
"kcp"
&&
i
>
0
{
glog
.
Fatal
(
"KCP must be the first node in the proxy chain"
)
if
(
node
.
Transport
==
"kcp"
||
node
.
Transport
==
"pht"
||
node
.
Transport
==
"quic"
)
&&
i
>
0
{
glog
.
Fatal
(
"KCP
/PHT/QUIC
must be the first node in the proxy chain"
)
}
}
...
...
@@ -118,6 +120,11 @@ func (c *ProxyChain) Init() {
c
.
kcpConfig
=
config
return
}
if
c
.
nodes
[
0
]
.
Transport
==
"pht"
{
glog
.
V
(
LINFO
)
.
Infoln
(
"Pure HTTP mode is enabled"
)
c
.
phttpClient
=
pht
.
NewClient
(
c
.
nodes
[
0
]
.
Addr
,
c
.
nodes
[
0
]
.
Get
(
"key"
))
}
}
func
(
c
*
ProxyChain
)
KCPEnabled
()
bool
{
...
...
@@ -269,6 +276,8 @@ func (c *ProxyChain) travelNodes(withHttp2 bool, nodes ...ProxyNode) (conn *Prox
cc
,
err
=
c
.
http2Connect
(
node
.
Addr
)
}
else
if
node
.
Transport
==
"kcp"
{
cc
,
err
=
c
.
getKCPConn
()
}
else
if
node
.
Transport
==
"pht"
{
cc
,
err
=
c
.
phttpClient
.
Dial
()
}
else
{
cc
,
err
=
net
.
DialTimeout
(
"tcp"
,
node
.
Addr
,
DialTimeout
)
}
...
...
cmd/gost/vendor/github.com/ginuerzh/gost/http.go
View file @
333291e9
...
...
@@ -4,14 +4,14 @@ import (
"bufio"
"crypto/tls"
"encoding/base64"
"errors"
"github.com/ginuerzh/pht"
"github.com/golang/glog"
"golang.org/x/net/http2"
"io"
"net"
"net/http"
"net/http/httputil"
//"strings"
"errors"
"time"
)
...
...
@@ -383,3 +383,30 @@ func (fw flushWriter) Write(p []byte) (n int, err error) {
}
return
}
type
PureHttpServer
struct
{
Base
*
ProxyServer
Handler
func
(
net
.
Conn
)
}
func
NewPureHttpServer
(
base
*
ProxyServer
)
*
PureHttpServer
{
return
&
PureHttpServer
{
Base
:
base
,
}
}
func
(
s
*
PureHttpServer
)
ListenAndServe
()
error
{
server
:=
pht
.
Server
{
Addr
:
s
.
Base
.
Node
.
Addr
,
Key
:
s
.
Base
.
Node
.
Get
(
"key"
),
}
if
server
.
Handler
==
nil
{
server
.
Handler
=
s
.
handleConn
}
return
server
.
ListenAndServe
()
}
func
(
s
*
PureHttpServer
)
handleConn
(
conn
net
.
Conn
)
{
glog
.
V
(
LINFO
)
.
Infof
(
"[pht] %s - %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
())
s
.
Base
.
handleConn
(
conn
)
}
cmd/gost/vendor/github.com/ginuerzh/gost/node.go
View file @
333291e9
...
...
@@ -71,7 +71,7 @@ func ParseProxyNode(s string) (node ProxyNode, err error) {
}
switch
node
.
Transport
{
case
"ws"
,
"wss"
,
"tls"
,
"http2"
,
"quic"
,
"kcp"
,
"redirect"
,
"ssu"
:
case
"ws"
,
"wss"
,
"tls"
,
"http2"
,
"quic"
,
"kcp"
,
"redirect"
,
"ssu"
,
"pht"
:
case
"https"
:
node
.
Protocol
=
"http"
node
.
Transport
=
"tls"
...
...
cmd/gost/vendor/github.com/ginuerzh/gost/server.go
View file @
333291e9
...
...
@@ -122,6 +122,8 @@ func (s *ProxyServer) Serve() error {
ttl
=
DefaultTTL
}
return
NewShadowUdpServer
(
s
,
ttl
)
.
ListenAndServe
()
case
"pht"
:
// pure http tunnel
return
NewPureHttpServer
(
s
)
.
ListenAndServe
()
default
:
ln
,
err
=
net
.
Listen
(
"tcp"
,
node
.
Addr
)
}
...
...
@@ -238,7 +240,7 @@ func (_ *ProxyServer) transport(conn1, conn2 net.Conn) (err error) {
select
{
case
err
=
<-
errc
:
//glog.V(LWARNING).Infoln("transport exit", err)
//
glog.V(LWARNING).Infoln("transport exit", err)
}
return
...
...
cmd/gost/vendor/github.com/ginuerzh/pht/LICENSE
0 → 100644
View file @
333291e9
MIT License
Copyright (c) 2017 ginuerzh
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
cmd/gost/vendor/github.com/ginuerzh/pht/README.md
0 → 100644
View file @
333291e9
# pht
Pure HTTP Tunnel - Tunnel over HTTP using only GET and POST requests.
cmd/gost/vendor/github.com/ginuerzh/pht/client.go
0 → 100644
View file @
333291e9
package
pht
import
(
"bufio"
"bytes"
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"strings"
"time"
)
type
Client
struct
{
Host
string
Key
string
httpClient
*
http
.
Client
manager
*
sessionManager
}
func
NewClient
(
host
,
key
string
)
*
Client
{
return
&
Client
{
Host
:
host
,
Key
:
key
,
httpClient
:
&
http
.
Client
{},
manager
:
newSessionManager
(),
}
}
func
(
c
*
Client
)
Dial
()
(
net
.
Conn
,
error
)
{
r
,
err
:=
http
.
NewRequest
(
http
.
MethodPost
,
fmt
.
Sprintf
(
"http://%s%s"
,
c
.
Host
,
tokenURI
),
nil
)
if
err
!=
nil
{
return
nil
,
err
}
r
.
Header
.
Set
(
"Authorization"
,
"key="
+
c
.
Key
)
resp
,
err
:=
c
.
httpClient
.
Do
(
r
)
if
err
!=
nil
{
return
nil
,
err
}
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
nil
,
errors
.
New
(
resp
.
Status
)
}
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
nil
,
err
}
token
:=
strings
.
TrimPrefix
(
string
(
data
),
"token="
)
if
token
==
""
{
return
nil
,
errors
.
New
(
"invalid token"
)
}
session
:=
newSession
(
0
,
0
)
c
.
manager
.
SetSession
(
token
,
session
)
go
c
.
sendDataLoop
(
token
)
go
c
.
recvDataLoop
(
token
)
return
newConn
(
session
),
nil
}
func
(
c
*
Client
)
sendDataLoop
(
token
string
)
error
{
session
:=
c
.
manager
.
GetSession
(
token
)
if
session
==
nil
{
return
errors
.
New
(
"invalid token"
)
}
for
{
select
{
case
b
,
ok
:=
<-
session
.
wchan
:
var
data
string
if
len
(
b
)
>
0
{
data
=
base64
.
StdEncoding
.
EncodeToString
(
b
)
}
r
,
err
:=
http
.
NewRequest
(
http
.
MethodPost
,
fmt
.
Sprintf
(
"http://%s%s"
,
c
.
Host
,
pushURI
),
bytes
.
NewBufferString
(
data
+
"
\n
"
))
if
err
!=
nil
{
return
err
}
r
.
Header
.
Set
(
"Authorization"
,
fmt
.
Sprintf
(
"key=%s; token=%s"
,
c
.
Key
,
token
))
if
!
ok
{
c
.
manager
.
DelSession
(
token
)
resp
,
err
:=
c
.
httpClient
.
Do
(
r
)
if
err
!=
nil
{
// TODO: retry
return
err
}
resp
.
Body
.
Close
()
return
nil
// session is closed
}
resp
,
err
:=
c
.
httpClient
.
Do
(
r
)
if
err
!=
nil
{
// TODO: retry
return
err
}
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
errors
.
New
(
resp
.
Status
)
}
}
}
}
func
(
c
*
Client
)
recvDataLoop
(
token
string
)
error
{
session
:=
c
.
manager
.
GetSession
(
token
)
if
session
==
nil
{
return
errors
.
New
(
"invalid token"
)
}
for
{
err
:=
c
.
recvData
(
token
,
session
)
if
err
!=
nil
{
close
(
session
.
rchan
)
c
.
manager
.
DelSession
(
token
)
return
err
}
}
}
func
(
c
*
Client
)
recvData
(
token
string
,
s
*
session
)
error
{
r
,
err
:=
http
.
NewRequest
(
http
.
MethodGet
,
fmt
.
Sprintf
(
"http://%s%s"
,
c
.
Host
,
pollURI
),
nil
)
if
err
!=
nil
{
return
err
}
r
.
Header
.
Set
(
"Authorization"
,
fmt
.
Sprintf
(
"key=%s; token=%s"
,
c
.
Key
,
token
))
resp
,
err
:=
c
.
httpClient
.
Do
(
r
)
if
err
!=
nil
{
return
err
}
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
errors
.
New
(
resp
.
Status
)
}
scanner
:=
bufio
.
NewScanner
(
resp
.
Body
)
for
scanner
.
Scan
()
{
select
{
case
<-
s
.
closed
:
return
errors
.
New
(
"session closed"
)
default
:
}
b
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
scanner
.
Text
())
if
err
!=
nil
{
return
err
}
select
{
case
s
.
rchan
<-
b
:
case
<-
s
.
closed
:
return
errors
.
New
(
"session closed"
)
case
<-
time
.
After
(
time
.
Second
*
90
)
:
return
errors
.
New
(
"timeout"
)
}
if
err
:=
scanner
.
Err
();
err
!=
nil
{
return
err
}
}
return
nil
}
cmd/gost/vendor/github.com/ginuerzh/pht/conn.go
0 → 100644
View file @
333291e9
package
pht
import
(
"errors"
"io"
"net"
"time"
)
type
conn
struct
{
session
*
session
rb
[]
byte
// read buffer
remoteAddr
net
.
Addr
localAddr
net
.
Addr
rTimer
,
wTimer
*
time
.
Timer
closed
chan
interface
{}
}
func
newConn
(
session
*
session
)
*
conn
{
conn
:=
&
conn
{
session
:
session
,
rTimer
:
time
.
NewTimer
(
time
.
Hour
*
65535
),
wTimer
:
time
.
NewTimer
(
time
.
Hour
*
65535
),
closed
:
make
(
chan
interface
{}),
}
conn
.
rTimer
.
Stop
()
conn
.
wTimer
.
Stop
()
return
conn
}
func
(
conn
*
conn
)
Read
(
b
[]
byte
)
(
n
int
,
err
error
)
{
select
{
case
<-
conn
.
closed
:
err
=
errors
.
New
(
"read: use of closed network connection"
)
return
default
:
}
if
len
(
conn
.
rb
)
>
0
{
n
=
copy
(
b
,
conn
.
rb
)
conn
.
rb
=
conn
.
rb
[
n
:
]
return
}
select
{
case
data
,
ok
:=
<-
conn
.
session
.
rchan
:
if
!
ok
{
err
=
io
.
EOF
return
}
n
=
copy
(
b
,
data
)
conn
.
rb
=
data
[
n
:
]
case
<-
conn
.
rTimer
.
C
:
err
=
errors
.
New
(
"read timeout"
)
case
<-
conn
.
closed
:
err
=
io
.
EOF
}
return
}
func
(
conn
*
conn
)
Write
(
b
[]
byte
)
(
n
int
,
err
error
)
{
select
{
case
<-
conn
.
closed
:
err
=
errors
.
New
(
"write: use of closed network connection"
)
return
default
:
}
if
len
(
b
)
==
0
{
return
}
data
:=
make
([]
byte
,
len
(
b
))
copy
(
data
,
b
)
select
{
case
conn
.
session
.
wchan
<-
data
:
n
=
len
(
b
)
case
<-
conn
.
wTimer
.
C
:
err
=
errors
.
New
(
"write timeout"
)
case
<-
conn
.
closed
:
err
=
errors
.
New
(
"connection is closed"
)
}
return
}
func
(
conn
*
conn
)
Close
()
error
{
close
(
conn
.
closed
)
close
(
conn
.
session
.
closed
)
close
(
conn
.
session
.
wchan
)
return
nil
}
func
(
conn
*
conn
)
LocalAddr
()
net
.
Addr
{
return
conn
.
localAddr
}
func
(
conn
*
conn
)
RemoteAddr
()
net
.
Addr
{
return
conn
.
remoteAddr
}
func
(
conn
*
conn
)
SetReadDeadline
(
t
time
.
Time
)
error
{
if
t
.
IsZero
()
{
conn
.
rTimer
.
Stop
()
return
nil
}
conn
.
rTimer
.
Reset
(
t
.
Sub
(
time
.
Now
()))
return
nil
}
func
(
conn
*
conn
)
SetWriteDeadline
(
t
time
.
Time
)
error
{
if
t
.
IsZero
()
{
conn
.
wTimer
.
Stop
()
return
nil
}
conn
.
wTimer
.
Reset
(
t
.
Sub
(
time
.
Now
()))
return
nil
}
func
(
conn
*
conn
)
SetDeadline
(
t
time
.
Time
)
error
{
if
t
.
IsZero
()
{
conn
.
rTimer
.
Stop
()
conn
.
wTimer
.
Stop
()
return
nil
}
d
:=
t
.
Sub
(
time
.
Now
())
conn
.
rTimer
.
Reset
(
d
)
conn
.
wTimer
.
Reset
(
d
)
return
nil
}
cmd/gost/vendor/github.com/ginuerzh/pht/server.go
0 → 100644
View file @
333291e9
package
pht
import
(
"bufio"
"encoding/base64"
"fmt"
"net"
"net/http"
"strings"
"time"
)
const
(
tokenURI
=
"/token"
pushURI
=
"/push"
pollURI
=
"/poll"
)
type
Server
struct
{
Addr
string
Key
string
Handler
func
(
net
.
Conn
)
manager
*
sessionManager
}
func
(
s
*
Server
)
ListenAndServe
()
error
{
s
.
manager
=
newSessionManager
()
mux
:=
http
.
NewServeMux
()
mux
.
Handle
(
tokenURI
,
http
.
HandlerFunc
(
s
.
tokenHandler
))
mux
.
Handle
(
pushURI
,
http
.
HandlerFunc
(
s
.
pushHandler
))
mux
.
Handle
(
pollURI
,
http
.
HandlerFunc
(
s
.
pollHandler
))
return
http
.
ListenAndServe
(
s
.
Addr
,
mux
)
}
func
(
s
*
Server
)
tokenHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
r
.
Method
!=
http
.
MethodPost
{
w
.
WriteHeader
(
http
.
StatusMethodNotAllowed
)
return
}
m
:=
parseAuth
(
r
.
Header
.
Get
(
"Authorization"
))
if
m
[
"key"
]
!=
s
.
Key
{
w
.
WriteHeader
(
http
.
StatusForbidden
)
return
}
token
,
session
,
err
:=
s
.
manager
.
NewSession
(
0
,
0
)
if
err
!=
nil
{
w
.
WriteHeader
(
http
.
StatusInternalServerError
)
return
}
conn
,
err
:=
s
.
upgrade
(
session
,
r
)
if
err
!=
nil
{
s
.
manager
.
DelSession
(
token
)
w
.
WriteHeader
(
http
.
StatusInternalServerError
)
return
}
if
s
.
Handler
!=
nil
{
go
s
.
Handler
(
conn
)
}
w
.
Write
([]
byte
(
fmt
.
Sprintf
(
"token=%s"
,
token
)))
}
func
(
s
*
Server
)
pushHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
r
.
Method
!=
http
.
MethodPost
{
w
.
WriteHeader
(
http
.
StatusMethodNotAllowed
)
return
}
m
:=
parseAuth
(
r
.
Header
.
Get
(
"Authorization"
))
if
m
[
"key"
]
!=
s
.
Key
{
w
.
WriteHeader
(
http
.
StatusForbidden
)
return
}
token
:=
m
[
"token"
]
session
:=
s
.
manager
.
GetSession
(
token
)
if
session
==
nil
{
w
.
WriteHeader
(
http
.
StatusUnauthorized
)
return
}
br
:=
bufio
.
NewReader
(
r
.
Body
)
data
,
err
:=
br
.
ReadString
(
'\n'
)
if
err
!=
nil
{
s
.
manager
.
DelSession
(
token
)
close
(
session
.
rchan
)
w
.
WriteHeader
(
http
.
StatusInternalServerError
)
return
}
data
=
strings
.
TrimSuffix
(
data
,
"
\n
"
)
if
len
(
data
)
==
0
{
s
.
manager
.
DelSession
(
token
)
close
(
session
.
rchan
)
return
}
b
,
err
:=
base64
.
StdEncoding
.
DecodeString
(
data
)
if
err
!=
nil
{
s
.
manager
.
DelSession
(
token
)
close
(
session
.
rchan
)
return
}
select
{
case
<-
session
.
closed
:
s
.
manager
.
DelSession
(
token
)
return
case
session
.
rchan
<-
b
:
w
.
WriteHeader
(
http
.
StatusOK
)
case
<-
time
.
After
(
time
.
Second
*
90
)
:
s
.
manager
.
DelSession
(
token
)
w
.
WriteHeader
(
http
.
StatusRequestTimeout
)
}
}
func
(
s
*
Server
)
pollHandler
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
if
r
.
Method
!=
http
.
MethodGet
{
w
.
WriteHeader
(
http
.
StatusMethodNotAllowed
)
return
}
m
:=
parseAuth
(
r
.
Header
.
Get
(
"Authorization"
))
if
m
[
"key"
]
!=
s
.
Key
{
w
.
WriteHeader
(
http
.
StatusForbidden
)
return
}
token
:=
m
[
"token"
]
session
:=
s
.
manager
.
GetSession
(
token
)
if
session
==
nil
{
w
.
WriteHeader
(
http
.
StatusUnauthorized
)
return
}
w
.
WriteHeader
(
http
.
StatusOK
)
if
fw
,
ok
:=
w
.
(
http
.
Flusher
);
ok
{
fw
.
Flush
()
}
for
{
select
{
case
data
,
ok
:=
<-
session
.
wchan
:
if
!
ok
{
s
.
manager
.
DelSession
(
token
)
return
// session is closed
}
bw
:=
bufio
.
NewWriter
(
w
)
bw
.
WriteString
(
base64
.
StdEncoding
.
EncodeToString
(
data
))
bw
.
WriteString
(
"
\n
"
)
if
err
:=
bw
.
Flush
();
err
!=
nil
{
return
}
if
fw
,
ok
:=
w
.
(
http
.
Flusher
);
ok
{
fw
.
Flush
()
}
case
<-
time
.
After
(
time
.
Second
*
25
)
:
return
}
}
}
func
(
s
*
Server
)
upgrade
(
sess
*
session
,
r
*
http
.
Request
)
(
net
.
Conn
,
error
)
{
conn
:=
newConn
(
sess
)
raddr
,
err
:=
net
.
ResolveTCPAddr
(
"tcp"
,
r
.
RemoteAddr
)
if
err
!=
nil
{
raddr
=
&
net
.
TCPAddr
{}
}
conn
.
remoteAddr
=
raddr
laddr
,
err
:=
net
.
ResolveTCPAddr
(
"tcp"
,
s
.
Addr
)
if
err
!=
nil
{
laddr
=
&
net
.
TCPAddr
{}
}
conn
.
localAddr
=
laddr
return
conn
,
nil
}
func
parseAuth
(
auth
string
)
map
[
string
]
string
{
mkv
:=
make
(
map
[
string
]
string
)
for
_
,
s
:=
range
strings
.
Split
(
auth
,
";"
)
{
n
:=
strings
.
Index
(
s
,
"="
)
if
n
<
0
{
continue
}
mkv
[
strings
.
TrimSpace
(
s
[
:
n
])]
=
strings
.
TrimSpace
(
s
[
n
+
1
:
])
}
return
mkv
}
cmd/gost/vendor/github.com/ginuerzh/pht/session.go
0 → 100644
View file @
333291e9
package
pht
import
(
"crypto/rand"
"encoding/hex"
"sync"
)
const
(
defaultRChanLen
=
64
defaultWChanLen
=
64
)
type
session
struct
{
rchan
chan
[]
byte
wchan
chan
[]
byte
closed
chan
interface
{}
}
func
newSession
(
rlen
,
wlen
int
)
*
session
{
if
rlen
<=
0
{
rlen
=
defaultRChanLen
}
if
wlen
<=
0
{
wlen
=
defaultWChanLen
}
return
&
session
{
rchan
:
make
(
chan
[]
byte
,
rlen
),
wchan
:
make
(
chan
[]
byte
,
wlen
),
closed
:
make
(
chan
interface
{}),
}
}
type
sessionManager
struct
{
sessions
map
[
string
]
*
session
mux
sync
.
Mutex
}
func
newSessionManager
()
*
sessionManager
{
return
&
sessionManager
{
sessions
:
make
(
map
[
string
]
*
session
),
mux
:
sync
.
Mutex
{},
}
}
func
(
m
*
sessionManager
)
NewSession
(
rlen
,
wlen
int
)
(
token
string
,
s
*
session
,
err
error
)
{
var
nonce
[
16
]
byte
if
_
,
err
=
rand
.
Read
(
nonce
[
:
]);
err
!=
nil
{
return
}
token
=
hex
.
EncodeToString
(
nonce
[
:
])
s
=
newSession
(
rlen
,
wlen
)
m
.
mux
.
Lock
()
defer
m
.
mux
.
Unlock
()
m
.
sessions
[
token
]
=
s
return
}
func
(
m
*
sessionManager
)
SetSession
(
token
string
,
session
*
session
)
{
m
.
mux
.
Lock
()
defer
m
.
mux
.
Unlock
()
m
.
sessions
[
token
]
=
session
}
func
(
m
*
sessionManager
)
GetSession
(
token
string
)
*
session
{
m
.
mux
.
Lock
()
defer
m
.
mux
.
Unlock
()
return
m
.
sessions
[
token
]
}
func
(
m
*
sessionManager
)
DelSession
(
token
string
)
{
m
.
mux
.
Lock
()
defer
m
.
mux
.
Unlock
()
delete
(
m
.
sessions
,
token
)
}
cmd/gost/vendor/vendor.json
View file @
333291e9
...
...
@@ -21,10 +21,16 @@
"revisionTime"
:
"2017-01-19T05:34:58Z"
},
{
"checksumSHA1"
:
"
VXFPGZtx+GKexkXeL3YljqJLHFk
="
,
"checksumSHA1"
:
"
ero0DQrGYph2eFDyEjDnOQV8NHo
="
,
"path"
:
"github.com/ginuerzh/gost"
,
"revision"
:
"dc75931858cf96d95525faa22b7ffa0cea3e7d68"
,
"revisionTime"
:
"2017-01-25T04:21:04Z"
"revision"
:
"72d8a598d50f8517d922f233e8f8d37011fcb18f"
,
"revisionTime"
:
"2017-01-25T04:23:26Z"
},
{
"checksumSHA1"
:
"+XIOnTW0rv8Kr/amkXgMraNeUr4="
,
"path"
:
"github.com/ginuerzh/pht"
,
"revision"
:
"f90acb425616767b84789d10e50a6fb652cd1e9a"
,
"revisionTime"
:
"2017-02-05T06:05:58Z"
},
{
"checksumSHA1"
:
"URsJa4y/sUUw/STmbeYx9EKqaYE="
,
...
...
http.go
View file @
333291e9
...
...
@@ -4,14 +4,14 @@ import (
"bufio"
"crypto/tls"
"encoding/base64"
"errors"
"github.com/ginuerzh/pht"
"github.com/golang/glog"
"golang.org/x/net/http2"
"io"
"net"
"net/http"
"net/http/httputil"
//"strings"
"errors"
"time"
)
...
...
@@ -383,3 +383,30 @@ func (fw flushWriter) Write(p []byte) (n int, err error) {
}
return
}
type
PureHttpServer
struct
{
Base
*
ProxyServer
Handler
func
(
net
.
Conn
)
}
func
NewPureHttpServer
(
base
*
ProxyServer
)
*
PureHttpServer
{
return
&
PureHttpServer
{
Base
:
base
,
}
}
func
(
s
*
PureHttpServer
)
ListenAndServe
()
error
{
server
:=
pht
.
Server
{
Addr
:
s
.
Base
.
Node
.
Addr
,
Key
:
s
.
Base
.
Node
.
Get
(
"key"
),
}
if
server
.
Handler
==
nil
{
server
.
Handler
=
s
.
handleConn
}
return
server
.
ListenAndServe
()
}
func
(
s
*
PureHttpServer
)
handleConn
(
conn
net
.
Conn
)
{
glog
.
V
(
LINFO
)
.
Infof
(
"[pht] %s - %s"
,
conn
.
RemoteAddr
(),
conn
.
LocalAddr
())
s
.
Base
.
handleConn
(
conn
)
}
node.go
View file @
333291e9
...
...
@@ -71,7 +71,7 @@ func ParseProxyNode(s string) (node ProxyNode, err error) {
}
switch
node
.
Transport
{
case
"ws"
,
"wss"
,
"tls"
,
"http2"
,
"quic"
,
"kcp"
,
"redirect"
,
"ssu"
:
case
"ws"
,
"wss"
,
"tls"
,
"http2"
,
"quic"
,
"kcp"
,
"redirect"
,
"ssu"
,
"pht"
:
case
"https"
:
node
.
Protocol
=
"http"
node
.
Transport
=
"tls"
...
...
server.go
View file @
333291e9
...
...
@@ -122,6 +122,8 @@ func (s *ProxyServer) Serve() error {
ttl
=
DefaultTTL
}
return
NewShadowUdpServer
(
s
,
ttl
)
.
ListenAndServe
()
case
"pht"
:
// pure http tunnel
return
NewPureHttpServer
(
s
)
.
ListenAndServe
()
default
:
ln
,
err
=
net
.
Listen
(
"tcp"
,
node
.
Addr
)
}
...
...
@@ -238,7 +240,7 @@ func (_ *ProxyServer) transport(conn1, conn2 net.Conn) (err error) {
select
{
case
err
=
<-
errc
:
//glog.V(LWARNING).Infoln("transport exit", err)
//
glog.V(LWARNING).Infoln("transport exit", err)
}
return
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment