This is a creation in Article, where the information may have evolved or changed.
Package Main
Import (
"OS"
"IO"
"FMT"
"NET"
"Strings"
"StrConv"
"Syscall"
"Encoding/binary"
)
Type Cspair struct {
Clientaddr Net. Addr
Serveraddr Net. Addr
Clientconn *net. Tcpconn
Serverconn *net. Tcpconn
}
Const (
SO_ORIGINAL_DST = 80
)
VAR (
Connection_count = 0
)
Func Main () {
LADDR: = &net. tcpaddr{}
Laddr. Port = 8838
ln, ERR: = Net. Listentcp ("TCP4", laddr)
Handle_error (ERR)
Fmt. Printf ("Listen on%d\n", Laddr. Port)
Defer Ln. Close ()
for {
Conn, err: = ln. ACCEPTTCP ()
Handle_error (ERR)
Pair: = construct_connection (conn)
Handle_data (pair)
}
}
Func handle_data (pair *cspair) {
Go Handle_cs (pair)
Go HANDLE_SC (pair)
}
Func Handle_cs (pair *cspair) {
Defer Pair.clientconn.Close ()
If strings. Index (Pair.serveraddr.String (), ": 843")! =-1 {
Fmt. Println (": 843 connection.")
Io. Copy (Pair.serverconn, Pair.clientconn)
Return
}
var remain_data []byte
for {
BS, err: = Readpacket (Pair.clientconn)
Handle_error (ERR)
Remain_data = append (Remain_data, BS ...)
Packet_len: = Int (binary. Littleendian.uint32 (Remain_data))
Packet_len + = 4//fixed len.
Fmt. Printf ("remain_data:0x%x, packet_len:0x%x\n", Len (Remain_data), Packet_len)
If Packet_len > Len (remain_data) {
Continue
}
Packet_data: = remain_data[:p Acket_len]
Remain_data = Remain_data[packet_len:]
Packet_data = append (packet_data, 0)
Fmt. Printf ("Receive 0x%x:%s\n", Packet_len, String (packet_data))
N, Err: = Pair.serverconn.Write (Packet_data)
Handle_error (ERR)
Fmt. Printf ("Handle_cs write 0x%x bytes\n", N)
}
}
Func handle_sc (pair *cspair) {
Defer Pair.serverconn.Close ()
Io. Copy (Pair.clientconn, Pair.serverconn)
Fmt. Println ("Handle_sc close Pair.serverconn")
/*
BS, err: = Readpacket (Pair.serverconn)
Handle_error (ERR)
Fmt. Printf ("handle_sc:%s\n", String (BS))
Pair.clientconn.Write (BS)
*/
}
Func construct_connection (c *net. Tcpconn) *cspair {
var pair = &cspair{}
Pair.clientconn = C
Pair.clientaddr = (*c). REMOTEADDR ()
F, err: = C.file ()
Handle_error (ERR)
Addr, err: = Syscall. Getsockoptipv6mreq (int (F.FD ()), Syscall. IPPROTO_IP, SO_ORIGINAL_DST)
Handle_error (ERR)
IPv4: = StrConv. Itoa (int (addr). MULTIADDR[4]) + "." +
StrConv. Itoa (int (addr). MULTIADDR[5]) + "." +
StrConv. Itoa (int (addr). MULTIADDR[6]) + "." +
StrConv. Itoa (int (addr). MULTIADDR[7]))
PORT: = UInt16 (addr. MULTIADDR[2]) << 8 + uint16 (addr. MULTIADDR[3])
Origin_ipv4: = IPv4
Origin_port: = Port
SA, err: = Net. RESOLVETCPADDR ("TCP4", FMT. Sprintf ("%s:%d", IPv4, port))
Handle_error (ERR)
PAIR.SERVERADDR = sa
Pair.serverconn, err = net. Dialtcp ("TCP4", Nil, SA)
Handle_error (ERR)
connection_count++
Fmt. Printf ("Accept%d,%s and create a new connection to server%s (%s:%d) \ n",
Connection_count, Pair.clientaddr.String (), pair.serveraddr.String (), Origin_ipv4, Origin_port)
Return pair
}
Func handle_error (err error) {
If err! = Nil {
Fmt. PRINTLN (ERR)
Os. Exit (1)
}
}