实现功能

This commit is contained in:
chenbox
2017-07-22 17:53:39 +08:00
parent e467fa58e8
commit 4fe6708a00
14 changed files with 366 additions and 301 deletions
+1
View File
@@ -8,3 +8,4 @@ src/launchpad.net
src/gopkg.in
src/ngrok/client/assets/
src/ngrok/server/assets/
.idea/
@@ -1,17 +1,13 @@
package client
import (
"crypto/md5"
"crypto/rand"
"encoding/base64"
"encoding/hex"
"fmt"
"io"
"log"
"net"
"os"
. "punching/constant"
"sync"
"time"
"punching/util"
)
var ListenAcceptMap map[string]net.Conn
@@ -19,34 +15,26 @@ var ExitChanMap map[string]chan bool
var RWLock *sync.RWMutex
//生成32位md5字串
func GetMd5String(s string) string {
h := md5.New()
h.Write([]byte(s))
return hex.EncodeToString(h.Sum(nil))
}
//生成Guid字串
func UniqueId() string {
b := make([]byte, 48)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return ""
}
return GetMd5String(base64.URLEncoding.EncodeToString(b))
}
func handleClientConn(source net.Conn) {
// 32位唯一码
uniqueid := UniqueId()
log.Println("Enter handleClientConn:", uniqueid)
// 4 bits unique session id
var sessionID string
for{
RWLock.Lock()
sessionID = util.GenerateRandomPairKey()
if _, ok := ListenAcceptMap[sessionID]; !ok{
break
}
RWLock.Unlock()
}
log.Println("Enter handleClientConn:", sessionID)
RWLock.Lock()
ListenAcceptMap[uniqueid] = source
ExitChanMap[uniqueid] = make(chan bool)
ListenAcceptMap[sessionID] = source
ExitChanMap[sessionID] = make(chan bool)
RWLock.Unlock()
log.Println("建立Map", uniqueid)
log.Println("建立Map", sessionID)
defer func() {
@@ -55,9 +43,9 @@ func handleClientConn(source net.Conn) {
log.Println("关闭Sourcer失败")
}
RWLock.Lock()
delete(ListenAcceptMap, uniqueid)
delete(ExitChanMap, uniqueid)
log.Println("删除map", uniqueid)
delete(ListenAcceptMap, sessionID)
delete(ExitChanMap, sessionID)
log.Println("删除map", sessionID)
RWLock.Unlock()
}()
@@ -75,18 +63,18 @@ func handleClientConn(source net.Conn) {
log.Println("读取Source源连接出错,原因为:", err.Error())
//发送控制
pack01 := Packet(uniqueid, "01", []byte(""))
Wch <- pack01
packQuit := util.PackageNat(PAIR_CONTROL_QUIT, [4]byte(sessionID),[]byte("") )
Wch <- packQuit
return
}
controlID := "00"
controlID := PAIR_CONTROL_NORMAL
if flag == 0 {
// 第一次
controlID = "11"
controlID = PAIR_CONTROL_FIRST
flag = 1
}
pack := Packet(uniqueid, controlID, buf[0:len01])
pack := util.PackageNat(controlID, [4]byte(sessionID), buf[0:len01])
Wch <- pack
}
@@ -94,7 +82,7 @@ func handleClientConn(source net.Conn) {
}()
select {
case <-ExitChanMap[uniqueid]:
case <-ExitChanMap[sessionID]:
log.Println("需要退出Accept")
return
}
@@ -108,6 +96,7 @@ func ClientListenHandle() {
RWLock = new(sync.RWMutex)
addrOn := Config.Dial
l, err := net.Listen("tcp", addrOn)
if err != nil {
fmt.Println("listen ", addrOn, " error:", err)
@@ -128,45 +117,39 @@ func ClientListenHandle() {
go handleClientConn(c)
}
}()
select {
case <-Dch:
os.Exit(3)
}
}
// 读取目标流到源
func handleReadConn() {
for {
select {
case r := <-Rch:
case pact := <-Rch:
log.Println(time.Now().UnixNano(), "handleReadConn准备处理")
// 获取src
controlid := r.ControlID
uniqueid := r.Key
data := r.Data
controlID := pact.ControlID
sessionID := string(pact.SessionID)
data := pact.Data
log.Println("读取Nat包:handleReadConn", uniqueid, "长度为", len(data))
log.Println("读取Nat包:handleReadConn", sessionID, "长度为", len(data))
//退出
if controlid == "01" {
if c, ok := ExitChanMap[uniqueid]; ok {
if controlID == PAIR_CONTROL_QUIT {
if c, ok := ExitChanMap[sessionID]; ok {
log.Println("发送退出信号")
c <- true
} else {
log.Println("在ExitChanMap里找不到Key为:", uniqueid)
log.Println("在ExitChanMap里找不到Key为:", sessionID)
}
} else {
if src, ok := ListenAcceptMap[uniqueid]; ok {
if src, ok := ListenAcceptMap[sessionID]; ok {
len2, err2 := src.Write(data)
if err2 != nil || len2 <= 0 {
log.Println("源写入出错", err2.Error())
}
log.Println(time.Now().UnixNano(), "源写入:", len2)
} else {
log.Println("在Map里找不到Key为:", uniqueid)
log.Println("在Map里找不到Key为:", sessionID)
}
}
+57 -8
View File
@@ -3,6 +3,15 @@ package client
import (
"fmt"
"log"
"punching/util"
"time"
"os"
)
var (
Dch chan bool
Rch chan util.PairPackage
Wch chan []byte
)
func Main() {
@@ -13,38 +22,78 @@ func Main() {
return
}
proxyAddr := Config.Dial || ThirdConfig.Address
proxyAddr := Config.Dial
if proxyAddr == "" {
proxyAddr = ThirdConfig.Address
}
pairName := Config.Key
localAddr, destAddr, pairname, err := util.ClientDialProxy(proxyAddr, pairName)
localAddr, destAddr, pairName, err := util.ClientDialProxy(proxyAddr, pairName)
if err != nil {
log.Println(err)
return
}
//连接对方
//连接P2P服务端
connPeer, errPeer := util.DialPeer(localAddr, destAddr)
if errPeer != nil { //无法连接上
log.Println(errPeer)
return
}
// 连接上 P2P客户端
Dch = make(chan bool)
Rch = make(chan DataPackage)
Rch = make(chan util.PairPackage)
Wch = make(chan []byte)
go RHandler(connPeer)
go WHandler(connPeer)
go RHandler(connPeer) //Nat端写通道
go WHandler(connPeer) //Nat端读通道
// 侦听端口,开启服务,将端口输入转发到P2P端
ClientListenHandle()
// 如果P2P端通讯出错,退出
select {
case <-Dch:
os.Exit(1)
}
}
func RHandler(conn util.NetConn) {
//声明一个临时缓冲区,用来存储被截断的数据
tmpBuffer := make([]byte, 0)
buff := make([]byte, 1024)
for {
j, err := conn.Read(buff)
if err != nil {
log.Println("读取连接数据出错,原因为:", err.Error())
Dch <- true
break
}
log.Println("准备解包数据:", j)
// 解包
tmpBuffer = util.UnpackageNat(append(tmpBuffer, buff[:j]...), Rch)
}
}
func WHandler(conn util.NetConn) {
for {
select {
case msg := <-Wch:
// prefix := string(msg[0:2])
// if prefix != "00" && prefix != "01" && prefix != "11" {
// log.Println("not equal", string(msg))
// } else {
l, err := conn.Write(msg)
if err != nil {
log.Println("写到Nat目录连接出错:", err.Error())
Dch <- true
} else {
log.Println(time.Now().UnixNano(), "已写入到Nat", l)
}
// }
}
}
}
-19
View File
@@ -1,19 +0,0 @@
package const
// Constant for the client and server
const (
PAIR_PACT_HEAD byte = 'P' // C<->S 自定义包头
PAIR_CONTROL_FIRST byte = 11 // 控制码 C->S第一个包
PAIR_CONTROL_QUIT byte = 10 // 控制码 退出
PAIR_CONTROL_NORMAL byte = 0 // 控制码
CLIENT_PAIR_ACK byte = 1 // 客户端匹配确认
SERVER_PAIR_ACK byte = 2 // 服务端匹配确认
)
const (
ROLE_SERVER int = 1 // 点对点服务端
ROLE_CLIENT int = 2 // 点对点客户端
}
-8
View File
@@ -1,8 +0,0 @@
package const
const (
PROXY_PACKAGE_HEAD byte = 'H' // C<->S 自定义包头
PROXY_CONTROL_ERROR_NO_SERVER byte = 201 // 服务端还没有注册
PROXY_CONTROL_ERROR_CLIENT_EXIST byte = 202 // 客户端已经存在
)
+29
View File
@@ -0,0 +1,29 @@
package constant
// Constant for the client and server
const (
PAIR_CONTROL_FIRST byte = 11 // 控制码 C->S第一个包
PAIR_CONTROL_QUIT byte = 10 // 控制码 退出
PAIR_CONTROL_NORMAL byte = 0 // 控制码
PAIR_PACKAGE_HEAD_LENGTH = 6 // C<->S 自定义包头长度
PAIR_PACKAGE_CONTROL_LENGTH = 1 // 包控制码长度
PAIR_PACKAGE_SESSIONID_LENGTH = 4 // 包会话ID长度
PAIR_PACKAGE_DATA_LENGTH = 4 // 包数据长度
PAIR_PACKAGE_PREFIX_LENGTH = 15 // head + control +sessionid + data length
)
const (
ROLE_SERVER byte = 1 // 点对点服务端
ROLE_CLIENT byte = 2 // 点对点客户端
)
var (
PAIR_PACKAGE_HEAD = [6]byte{'C','B','X','N','A','T'} // C<->S 自定义包头
)
+14
View File
@@ -0,0 +1,14 @@
package constant
const (
PROXY_PACKAGE_HEAD byte = 'H' // C<->S 自定义包头
PROXY_CONTROL_FIRST byte = 11 // 控制ID 第一个数据包
PROXY_CONTROL_NORMAL byte = 0 // 控制码 正常发送
PROXY_CONTROL_ACK byte = 12 // 控制码 确认
PROXY_CONTROL_QUIT byte = 10 // 控制码 退出
PROXY_CONTROL_ERROR_NO_SERVER byte = 201 // 服务端还没有注册
PROXY_CONTROL_ERROR_CLIENT_EXIST byte = 202 // 客户端已经存在
PROXY_CONTROL_ERROR_SERVER_EXIST byte = 203 // 服务端已经存在
)
+48 -54
View File
@@ -5,24 +5,11 @@ import (
"sync"
"fmt"
"punching/util"
"punching/logger"
"time"
"punching/const"
. "punching/constant"
"log"
)
const (
PROXY_FIRST_HEAD byte = 'P' //包头标识
ROLE_SERVER byte = 1 //服务端
ROLE_CLIENT byte = 2 //客户端
PROXY_RESP_NO_SERVER = "no_server_partner" // 代理响应-服务端还没有启用
PROXY_RESP_CLIENT_EXIST = "client_existed" // 代理响应-客户端已经存在了
PROXY_RESP_ERR_SERVER_EXIST = "server_existed" // 代理响应-客户端已经存在了
CLIENT_RESP_ACK byte = 1
SERVER_RESP_ACK byte = 1
)
// ServerConn 服务端到代理端连接
type ServerConn struct {
Rch chan []byte // 读通道
@@ -40,10 +27,10 @@ type ClientConn struct{
// 全局变量
var (
OnlineServerList map[string]ServerConn // 服务端连接列表Map
OnlineClientList map[string]ClientConn // 客户端连接列表Map
RWLockClient sync.RWMutex //读写锁
RWLockServer sync.RWMutex
OnlineServerList map[string]*ServerConn // 服务端连接列表Map
OnlineClientList map[string]*ClientConn // 客户端连接列表Map
RWLockClient *sync.RWMutex //读写锁
RWLockServer *sync.RWMutex
)
func Main(){
@@ -54,14 +41,14 @@ func Main(){
return
}
OnlineServerList = make(map[string]ServerConn)
OnlineClientList = make(map[string]ClientConn)
OnlineServerList = make(map[string]*ServerConn)
OnlineClientList = make(map[string]*ClientConn)
RWLockClient = new(sync.RWMutex)
RWLockServer = new(sync.RWMutex)
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
listenAddr := Config.Listen
tcpAddr, err := net.ResolveTCPAddr("tcp", listenAddr)
if err != nil {
panic(err)
}
@@ -87,19 +74,15 @@ func Main(){
// parseFirstPackage 解析连接的第一个条
// [1]+[1]+[4-32] (包头标识+类型+32字节的Pairname)
func parseFirstPackage(data []byte)(pairname string, roleType int, err error){
if len(data) <= 6 || len(data) > 34 {
err = fmt.Errorf("%s","包长度不匹配")
return
}
func parseFirstPackage(data []byte)(pairName string, roleType int, err error){
roleType = int(data[1])
if data[0] != PROXY_FIRST_HEAD || ( roleType != ROLE_CLIENT && roleType != ROLE_SERVER) {
if data[0] != PROXY_PACKAGE_HEAD || ( roleType != ROLE_CLIENT && roleType != ROLE_SERVER) {
err = fmt.Errorf("%s","包内容不匹配")
return
}
pairname = string(byte[2:])
pairName = string(byte[2:])
return
}
@@ -184,15 +167,16 @@ func Handler(conn net.Conn) {
defer func() {
if r := recover(); r != nil {
logger.Println("连接出现问题:%s",r.Error())
fmt.Printf("连接出现问题:%s",r)
}
}()
defer conn.Close()
buf := make([]byte, 1024)
var uid string
var C *OnlineServerSide
var pairName string
var C *ServerConn
// 确定连接类型,判断是否是有效的连接,
// 对于客户端,需满足
@@ -211,43 +195,53 @@ func Handler(conn net.Conn) {
}
//获取匹配名称和连接类型(服务端或客户端)
pairname, roleType, err := parseFirstPackage(buf[0:i])
pairName, roleType, err := parseFirstPackage(buf[0:i])
if err != nil {
return
}
// 处理客户端连接
if roleType == ROLE_CLIENT{
processRoleClient(conn)
return // 退出客户端连接
}
break
break
}
// 下面的操作都是针对服务端连接
// 是否存在pair name
RWLockServer.RLock()
_, ok := OnlineServerList[pairname]
RWLockServer.RUnlock()
// 已存在
if ok {
conn.Write([]byte(PROXY_RESP_ERR_SERVER_EXIST))
return
// 服务端连接允许匹配码为空,系统将随机产生唯一匹配码
if pairName == ""{
for{
pairName = util.GenerateRandomPairKey()
RWLockServer.Lock()
if _, ok := OnlineServerList[pairName]; !ok {
break;
}
RWLockServer.Unlock()
}
}else{
// 是否存在pair name
RWLockServer.RLock()
_, ok := OnlineServerList[pairName]
RWLockServer.RUnlock()
// 已存在
if ok {
errPack := util.PackageProxy(PROXY_CONTROL_ERROR_SERVER_EXIST, []byte(""))
conn.Write(errPack)
fmt.Printf("服务端列表中已存在:%s", pairName)
return
}
}
// 生成服务器连接对象添加到列表
RWLockServer.Lock()
serverConn := &ServerConn{Rch: make(chan []byte), Wch: make(chan []byte), Pairname: pairname, LocalAddr: conn.LocalAddr}
OnlineServerList[pairname] = serverConn
serverConn := &ServerConn{Rch: make(chan []byte), Wch: make(chan []byte), Pairname: pairName, LocalAddr: conn.LocalAddr().String()}
OnlineServerList[pairName] = serverConn
RWLockServer.Unlock()
// 写通道
@@ -1,4 +1,4 @@
package client
package server
import (
"log"
+6 -1
View File
@@ -15,9 +15,14 @@ func Main() {
return
}
proxyAddr := Config.Dial || ThirdConfig.Address
// Proxy Server Address
proxyAddr := Config.Dial
if proxyAddr == "" {
proxyAddr = ThirdConfig.Address
}
pairName := Config.Key
// 如果跟Peer连接出错,要重新连接Proxy
for {
+53 -34
View File
@@ -4,26 +4,34 @@ import (
"fmt"
"log"
"net"
"os"
"punching/util"
. "punching/constant"
"strings"
)
var (
ProxyDch chan byte
ProxyRch chan []byte
ProxyWch chan []byte
)
func WaitForPeer(conn util.NetConn) (localAddr string, remoteAddr string, pairname string, err error) {
func WaitForPeer(conn util.NetConn) (localAddr string, remoteAddr string, err error) {
// 接收心跳和客户端连接确认
Rch = make(chan DataPackage)
Wch = make(chan []byte)
ProxyRch = make(chan []byte)
ProxyWch = make(chan []byte)
go RProxyHandler(conn)
go RHandler(conn)
go WHandler(conn)
select {
case ret := <-Dch:
case ret := <-ProxyDch:
switch ret {
case 10: //无法跟proxy连接
case PROXY_CONTROL_QUIT: //无法跟proxy连接
//关闭连接
err = error("出现错误")
break
case 11: // 获取客户端发来信息
case PROXY_CONTROL_NORMAL: // 获取客户端发来信息
localAddr = ""
remoteAddr = ""
pairName = ""
@@ -34,13 +42,13 @@ func WaitForPeer(conn util.NetConn) (localAddr string, remoteAddr string, pairna
}
}
func ServerDialProxy(proxyAddr string, pairkey string) (conn util.NetConn, err error) {
func ServerDialProxy(proxyAddr string, pairName string) (retConn util.NetConn, err error) {
// 发第一个包
// 地址接收确认
// 心跑包接收和确认
var conn = util.NetConn{}
var conn util.NetConn
// 不指定端口,让系统自动分配
err = conn.Bind("tcp", "")
@@ -57,43 +65,54 @@ func ServerDialProxy(proxyAddr string, pairkey string) (conn util.NetConn, err e
fmt.Println("连接服务端出错", err.Error())
return
}
defer conn.Close()
fmt.Println("已连接服务器,服务器地址是:%s:%d", tcpAddr.IP.String(), tcpAddr.Port)
// 发送第一个包
PackageProxy()
key := "ok" + name
buff01 := make([]byte, len(key))
// 构造自定义包
data := make([]byte, 4)
data = append(data, []byte{ROLE_SERVER}...)
data = append(data, []byte(pairName)...)
//发送第一个包
log.Println("发送数据1", name)
n, err := conn.Write([]byte(name))
packFirst := util.PackageProxy(PROXY_CONTROL_FIRST, data)
_, err = conn.Write(packFirst)
if err != nil {
log.Println("出错,原因:", err.Error())
os.Exit(22)
return
}
log.Println("have write: ", n)
// 读取
// 错误,退出此次连接
// 没有错误,显示当前连接的信息
i, err := conn.Read(buff01)
buff := make([]byte, 1024)
// 获取返回信息
i, err := conn.Read(buff)
if err != nil {
fmt.Println("读取数据出错,", err.Error())
os.Exit(1)
return
}
// log.Print("读取数据:", string(buff01[0:i]))
// if string(buff01[0:i]) == key {
// break
// }
// log.Println("发送数据", []byte(name))
// conn.Write([]byte(name))
controlID := buff[1]
switch controlID {
case PROXY_CONTROL_NORMAL:
retData := string(buff[2:i])
items := strings.Split(retData, ",")
localAddr := items[0]
rePairName := items[1]
fmt.Printf("P2P服务端侦听地址为:%s, 匹配码为:%s", localAddr, rePairName)
break
case PROXY_CONTROL_ERROR_SERVER_EXIST:
err = fmt.Errorf("错误,P2P服务端已存在")
break
default:
err = fmt.Errorf("无效的控制码,%d",int(controlID))
}
return conn, nil
}
func RHandler(conn util.NetConn) {
func RProxyHandler(conn util.NetConn) {
for {
// 心跳包,回复ack
+56 -65
View File
@@ -4,34 +4,32 @@ import (
"fmt"
"log"
"net"
"os"
"p2p/util"
"strings"
"time"
. "punching/constant"
"strings"
)
// 连接到Proxy代理解析端, 地址/类型/IP
// 发送第一个包->(接收到错误数据,退出,否则接收到NatAddress,->确认收到 <->完成 不断接收心跳包,确认)
// 客户端 错误失败 | nat地址
// 服务端 错误失败 | 注册 心跑包
func ClientDialProxy(proxyAddr string, pairkey string, role string) (localAddr string, destAddr string, pairname string, err error) {
// 发第一个包
// 地址接收确认
// 心跑包接收和确认
// ClientDialProxy P2P客户端连接到Proxy
// 连接成功后获取本地地址,远程地址和匹配码,否则将返回错误
func ClientDialProxy(proxyAddr string, pairName string) (localAddr string, remoteAddr string, rePairName string, err error) {
var conn = util.NetConn{}
var conn = NetConn{}
// 不指定端口,让系统自动分配
err = conn.Bind("tcp", "")
if err != nil {
log.Println("绑定出错", err.Error())
fmt.Println("绑定出错", err.Error())
return
}
// 连接到Proxy解析服务器
tcpAddr, err := net.ResolveTCPAddr("tcp", proxyAddr)
err = conn.Connect(util.InetAddr(tcpAddr.IP.String()), tcpAddr.Port)
err = conn.Connect(InetAddr(tcpAddr.IP.String()), tcpAddr.Port)
if err != nil {
fmt.Println("连接服务端出错", err.Error())
@@ -40,69 +38,62 @@ func ClientDialProxy(proxyAddr string, pairkey string, role string) (localAddr s
defer conn.Close()
fmt.Println("已连接服务器,服务器地址是:%s:%d", tcpAddr.IP.String(), tcpAddr.Port)
for {
// 构造自定义包
data := make([]byte, 4)
data = append(data, []byte{ROLE_CLIENT}...)
data = append(data, []byte(pairName)...)
PackageProxy()
packFirst := PackageProxy(PROXY_CONTROL_FIRST, data)
key := "ok" + name
buff01 := make([]byte, len(key))
//发送第一个包
log.Println("发送数据1", name)
n, err := conn.Write([]byte(name))
if err != nil {
log.Println("出错,原因:", err.Error())
os.Exit(22)
}
log.Println("have write: ", n)
i, err := conn.Read(buff01)
if err != nil {
fmt.Println("读取数据出错,", err.Error())
os.Exit(1)
}
log.Print("读取数据:", string(buff01[0:i]))
if string(buff01[0:i]) == key {
break
}
log.Println("发送数据", []byte(name))
conn.Write([]byte(name))
}
fmt.Println("--- Request sent, waiting for parkner in Name ...", name)
buff := make([]byte, 512)
//获取服务发送过来的对方IP信息
len, err := conn.Read(buff)
_, err = conn.Write(packFirst)
if err != nil {
log.Println("客户端读取数据出错:", err.Error())
os.Exit(1)
return
}
pairAddr := string(buff[0:len])
arrPairAddr := strings.Split(pairAddr, ",")
remoteAddrStr := arrPairAddr[0]
localAddrStr := arrPairAddr[1]
log.Println("读取到远程IP", remoteAddrStr)
buff := make([]byte, 1024)
conn.Close()
//time.Sleep(3 * time.Second)
// 获取返回信息
i, err := conn.Read(buff)
if err != nil {
fmt.Println("读取数据出错,", err.Error())
return
}
remoteAddr, err := net.ResolveTCPAddr("tcp", remoteAddrStr)
controlID := buff[1]
switch controlID {
case PROXY_CONTROL_NORMAL:
retData := string(buff[2:i])
items := strings.Split(retData, ",")
localAddr = items[0]
remoteAddr = items[1]
rePairName = items[2]
//localAddr.String()
log.Println("local addr:", localAddrStr)
// 发送确认
packAck := PackageProxy(PROXY_CONTROL_ACK, []byte(""))
conn.Write(packAck)
break
case PROXY_CONTROL_ERROR_NO_SERVER:
err = fmt.Errorf("错误,P2P服务端不存在")
break
case PROXY_CONTROL_ERROR_CLIENT_EXIST:
err = fmt.Errorf("错误,P2P服务端不存在")
break
default:
err = fmt.Errorf("无效的控制码,%d",int(controlID))
}
return
}
func DialPeer(localAddr string, remoteAddr string) util.NetConn {
func DialPeer(localAddr string, remoteAddr string) (netconn NetConn, err error) {
remoteTCPAddr, err := net.ResolveTCPAddr("tcp", remoteAddr)
if err != nil {
log.Println("The format of remote address is invalid, %s", err.Error())
return
}
var conn util.NetConn
var conn NetConn
// 不指定端口,让系统自动分配
err = conn.Bind("tcp", localAddr)
@@ -111,19 +102,19 @@ func DialPeer(localAddr string, remoteAddr string) util.NetConn {
return
}
// TODO 应该封装成一个函数
// 有时连接并不成功,多次连接
log.Println("远程地址是:", remoteAddr.IP.String(), remoteAddr.Port)
log.Println("远程地址是:", remoteTCPAddr.IP.String(), remoteTCPAddr.Port)
// 有时连接一次并不成功,尝试多次连接
tryCount := 0
for {
tryCount += 1
if tryCount > 10 {
log.Printf("连接不上,退出")
err = fmt.Errorf("Attempt to connect remote address, but failed, local addrss: %s, "+
"remote address", localAddr, remoteAddr)
return
}
err02 := conn02.Connect(util.InetAddr(remoteAddr.IP.String()), remoteAddr.Port)
err02 := conn.Connect(util.InetAddr(remoteTCPAddr.IP.String()), remoteTCPAddr.Port)
if err02 != nil {
log.Printf("第%d次不能连接远程服务器:%s", tryCount, err02.Error())
time.Sleep(1 * time.Second)
@@ -133,5 +124,5 @@ func DialPeer(localAddr string, remoteAddr string) util.NetConn {
break
}
}
return conn, nil
}
+60 -34
View File
@@ -1,61 +1,87 @@
package util
package util
const {
PACKAGE_PROXY_HEADER byte = 'P'
PACKAGE_NAT_HEADER [6]byte = []byte{'C','B','X','N','A','T'}
import (
"bytes"
. "punching/constant"
"log"
)
// PairPackage P2P端通讯封装包
type PairPackage struct {
Head [6]byte // 头
ControlID byte // 控制ID
SessionID [4]byte // 会话ID
Data []byte // 数据
}
// 跟代理解析端通讯封包
func PackageProxy(control byte, data []byte) []byte{
func PackageProxy(control byte, data []byte) []byte {
pack := bytes.NewBuffer(nil)
pack.Write(PACKAGE_PROXY_HEADER)
pack.Write(control)
pack.Write([]byte{PROXY_PACKAGE_HEAD})
pack.Write([]byte{control})
pack.Write(data)
return pack.Bytes()
}
// 跟代理解析端通讯拆包
func UnpackageProxy(pact []byte)(control byte, data []byte) {
// 跟代理解析端拆包
func UnpackageProxy(pact []byte) (control byte, data []byte) {
return pact[1], pact[1:]
}
// Nat网络后面的Client端和Server端封包
func PackageNat(control byte, sessionKey [4]byte, data []byte) []byte{
// Customize P2P data package
// The format of package defined below:
// head(6)+control(1)+session id(4) + data length (4) + data
func PackageNat(control byte, sessionID [4]byte, data []byte) []byte {
pack := bytes.NewBuffer(nil)
pack.Write([]byte(PAIR_PACKAGE_HEAD)) // Head [6]byte
pack.Write([]byte{control})
pack.Write([]byte(sessionID))
pack.Write(IntToBytes(len(data))) // length of sent data
pack.Write([]byte(sessionID))
pack.Write(data)
return pack.Bytes()
}
// Nat网络后面的Client端和Server端拆包
// 需要考虑沾包,分析出的完整封装包传入读channel
func UnpackageNat(pact []byte)(data []byte){
func UnpackageNat(buffer []byte, readChan chan PairPackage) (data []byte) {
length := len(buffer)
log.Println("长度为:", length)
var i int
for i = 0; i < length; i = i + 1 {
if length < i+ConstHeaderLength+ConstControlLength+ConstDataLength {
if length < i + PAIR_PACKAGE_PREFIX_LENGTH {
break
}
if string(buffer[i:i+len(ConstHeaderKey)]) == ConstHeaderKey {
// 获取头数据长度
messageLength := BytesToInt(buffer[i+ConstHeaderLength+ConstControlLength : i+ConstHeaderLength+ConstControlLength+ConstDataLength])
log.Println("数据长度为:", messageLength)
log.Println("需要的包长度:", ConstHeaderLength+ConstControlLength+ConstDataLength+messageLength)
if length < i+ConstHeaderLength+ConstControlLength+ConstDataLength+messageLength {
if string(buffer[i:i+ PAIR_PACKAGE_HEAD_LENGTH]) == string(PAIR_PACKAGE_HEAD) {
// Length of data
dataLength := BytesToInt(buffer[i+ PAIR_PACKAGE_PREFIX_LENGTH - PAIR_PACKAGE_DATA_LENGTH: i +
PAIR_PACKAGE_PREFIX_LENGTH])
if length < i+ PAIR_PACKAGE_PREFIX_LENGTH + dataLength {
break
}
data := buffer[i+ConstHeaderLength+ConstControlLength+ConstDataLength : i+ConstHeaderLength+ConstControlLength+ConstDataLength+messageLength]
controlID := string(buffer[i+ConstHeaderLength : i+ConstHeaderLength+ConstControlLength])
key := string(buffer[i+len(ConstHeaderKey) : i+ConstHeaderLength])
log.Println("控制ID为:", controlID, "key为", key)
dataPackage := DataPackage{
Data: data,
ControlID: controlID,
Key: key,
}
Rch <- dataPackage
i += ConstHeaderLength + ConstControlLength + ConstDataLength + messageLength - 1
// data
data := buffer[i + PAIR_PACKAGE_PREFIX_LENGTH: i + PAIR_PACKAGE_PREFIX_LENGTH +
dataLength]
controlID := buffer[i + PAIR_PACKAGE_HEAD_LENGTH : i + PAIR_PACKAGE_HEAD_LENGTH +
PAIR_PACKAGE_CONTROL_LENGTH]
sessionID := string(buffer[i+ PAIR_PACKAGE_HEAD_LENGTH + PAIR_PACKAGE_CONTROL_LENGTH:
i + PAIR_PACKAGE_HEAD_LENGTH + PAIR_PACKAGE_CONTROL_LENGTH + PAIR_PACKAGE_SESSIONID_LENGTH])
pact := PairPackage{
Head: PAIR_PACKAGE_HEAD,
Data: data,
ControlID: controlID[0],
SessionID: [4]byte(sessionID),
}
readChan <- pact
i += PAIR_PACKAGE_PREFIX_LENGTH + dataLength - 1
}
}
@@ -64,4 +90,4 @@ func UnpackageNat(pact []byte)(data []byte){
}
return buffer[i:]
}
}
+5 -24
View File
@@ -1,30 +1,10 @@
package util
import (
"crypto/md5"
"crypto/rand"
"encoding/base64"
"encoding/hex"
"io"
"math/rand"
"time"
)
//生成32位md5字串
func GetMd5String(s string) string {
h := md5.New()
h.Write([]byte(s))
return hex.EncodeToString(h.Sum(nil))
}
//生成Guid字串
func UniqueId() string {
b := make([]byte, 48)
if _, err := io.ReadFull(rand.Reader, b); err != nil {
return ""
}
return GetMd5String(base64.URLEncoding.EncodeToString(b))
}
// GenerateRandomPairKey 获取4位随机匹配码
func GenerateRandomPairKey() string {
@@ -32,20 +12,21 @@ func GenerateRandomPairKey() string {
rndNums := GenerateRandomNumber(97, 122, 4)
key := ""
for num, _ := range rndNums {
key = key + string(byte{num})
key = key + string(byte(num))
}
return key
}
//生成count个[start,end)结束的不重复的随机数
func GenerateRandomNumber(start int, end int, count int) []int {
//范围检查
// Check the range
if end < start || (end-start) < count {
return nil
}
//存放结果的slice
// Slice to store the result
nums := make([]int, 0)
//随机数生成器,加入时间戳保证每次生成的随机数不一样
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for len(nums) < count {
//生成随机数