/
rserver.go
85 lines (77 loc) · 1.92 KB
/
rserver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package main
import (
"crypto/tls"
"net"
"sync/atomic"
"time"
log "github.com/liudanking/log4go"
)
type RemoteServer struct {
laddr string
raddr string
streamID uint64
streamCount int32
}
func NewRemoteServer(laddr, raddr string) (*RemoteServer, error) {
rs := &RemoteServer{
laddr: laddr,
raddr: raddr,
streamCount: 0,
}
return rs, nil
}
func (rs *RemoteServer) Serve(certFile, keyFile string) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
log.Error("load cert/key error:%v", err)
return
}
config := tls.Config{
Certificates: []tls.Certificate{cert},
}
l, err := tls.Listen("tcp", rs.laddr, &config)
if err != nil {
log.Error("net.ListenTCP(%s) error:%v", rs.laddr, err)
return
}
for {
stream, err := l.Accept()
if err != nil {
log.Error("listenner accept connection error:%v", err)
continue
}
go rs.serveStream(stream)
}
}
func (rs *RemoteServer) serveStream(stream net.Conn) {
defer stream.Close()
start := time.Now()
conn, err := net.Dial("tcp", rs.raddr)
if err != nil {
log.Error("connect to remote error:%v", err)
return
}
defer conn.Close()
atomic.AddInt32(&rs.streamCount, 1)
streamID := atomic.AddUint64(&rs.streamID, 1)
readChan := make(chan int64, 1)
writeChan := make(chan int64, 1)
var readBytes int64
var writeBytes int64
go pipe(stream, conn, readChan)
go pipe(conn, stream, writeChan)
for i := 0; i < 2; i++ {
select {
case readBytes = <-readChan:
stream.Close()
log.Debug("[#%d] read %d bytes", streamID, readBytes)
case writeBytes = <-writeChan:
// DON'T call conn.Close, it will trigger an error in pipe.
// Just close stream, let the conn copy finished normally
log.Debug("[#%d] write %d bytes", streamID, writeBytes)
}
}
log.Info("[#%d] r:%d w:%d t:%v c:%d",
streamID, readBytes, writeBytes, time.Now().Sub(start), atomic.LoadInt32(&rs.streamCount))
atomic.AddInt32(&rs.streamCount, -1)
}