Browse Source

Determine the hole punching technique

link 3 years ago
parent
commit
28c1a52171
11 changed files with 347 additions and 24 deletions
  1. 4 1
      main.go
  2. 14 0
      model/person.go
  3. 1 0
      model/zima.go
  4. 44 0
      pkg/utils/file/block.go
  5. 2 2
      pkg/utils/httper/httper.go
  6. 11 2
      route/v1/file.go
  7. 8 1
      route/v1/persion.go
  8. 255 4
      service/person.go
  9. 6 13
      service/socket.go
  10. 1 1
      service/zima_info.go
  11. 1 0
      types/block.go

+ 4 - 1
main.go

@@ -32,7 +32,10 @@ func init() {
 	//gredis.GetRedisConn(config.RedisInfo),
 	//gredis.GetRedisConn(config.RedisInfo),
 	service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
 	service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
 	service.Cache = cache.Init()
 	service.Cache = cache.Init()
-	go service.SocketConnect()
+	//go service.SocketConnect()
+	//go service.TestTCP()
+	//go service.TestTCPOne()
+	go service.TestTCPTwo()
 	route.InitFunction()
 	route.InitFunction()
 
 
 }
 }

+ 14 - 0
model/person.go

@@ -21,4 +21,18 @@ type MessageModel struct {
 	Type string      `json:"type"`
 	Type string      `json:"type"`
 	Data interface{} `json:"data"`
 	Data interface{} `json:"data"`
 	UUId string      `json:"uuid"`
 	UUId string      `json:"uuid"`
+	From string      `json:"from"`
+}
+
+type TranFileModel struct {
+	Hash  string `json:"hash"` //Verify current fragment integrity
+	Data  []byte `json:"data"`
+	Index int    `json:"index"`
+}
+
+type FileSummaryModel struct {
+	Hash      string `json:"hash"` //Verify file
+	Name      string `json:"name"`
+	Path      string `json:"path"`
+	BlockSize int    `json:"block_size"`
 }
 }

+ 1 - 0
model/zima.go

@@ -7,4 +7,5 @@ type Path struct {
 	Path  string    `json:"path"`
 	Path  string    `json:"path"`
 	IsDir bool      `json:"is_dir"`
 	IsDir bool      `json:"is_dir"`
 	Date  time.Time `json:"date"`
 	Date  time.Time `json:"date"`
+	Size  int64     `json:"size"`
 }
 }

+ 44 - 0
pkg/utils/file/block.go

@@ -0,0 +1,44 @@
+package file
+
+import (
+	"crypto/md5"
+	"encoding/hex"
+	"math"
+)
+
+// Get info of block
+func GetBlockInfo(fileSize int) (blockSize int, length int) {
+	switch {
+	case fileSize <= 1<<28: //256M
+		blockSize = 1 << 17 //128kb
+	case fileSize <= 1<<29: //512M
+		blockSize = 1 << 18 //256kb
+	case fileSize <= 1<<30: //1G
+		blockSize = 1 << 19 //512kb
+	case fileSize <= 1<<31: //2G
+		blockSize = 1 << 20 //(mb)
+	case fileSize <= 1<<32: //4G
+		blockSize = 1 << 21 //2mb
+	case fileSize <= 1<<33: //8G
+		blockSize = 1 << 22 //4mb
+	case fileSize <= 1<<34: //16g
+		blockSize = 1 << 23 //8mb
+	default:
+		blockSize = 1 << 24 //16mb
+	}
+	temp := float64(fileSize) / float64(blockSize)
+	length = int(math.Ceil(temp))
+	return
+}
+
+//get the hash of the data
+func GetHash(data []byte) string {
+	sum := md5.Sum(data)
+	return hex.EncodeToString(sum[:])
+}
+
+//Comparison data hash
+func ComparisonHash(data []byte, hash string) bool {
+	sum := md5.Sum(data)
+	return hex.EncodeToString(sum[:]) == hash
+}

+ 2 - 2
pkg/utils/httper/httper.go

@@ -16,9 +16,9 @@ import (
 //url:请求地址
 //url:请求地址
 //response:请求返回的内容
 //response:请求返回的内容
 func Get(url string, head map[string]string) (response string) {
 func Get(url string, head map[string]string) (response string) {
-	client := http.Client{Timeout: 30 * time.Second}
+	client := &http.Client{Timeout: 30 * time.Second}
 	req, err := http.NewRequest("GET", url, nil)
 	req, err := http.NewRequest("GET", url, nil)
-	req.BasicAuth()
+
 	for k, v := range head {
 	for k, v := range head {
 		req.Header.Add(k, v)
 		req.Header.Add(k, v)
 	}
 	}

+ 11 - 2
route/v1/file.go

@@ -196,8 +196,8 @@ func RenamePath(c *gin.Context) {
 		c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
 		c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
 		return
 		return
 	}
 	}
-	service.MyService.ZiMa().RenameFile(op, np)
-	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
+	success, err := service.MyService.ZiMa().RenameFile(op, np)
+	c.JSON(http.StatusOK, model.Result{Success: success, Message: oasis_err2.GetMsg(success), Data: err})
 }
 }
 
 
 // @Summary create folder
 // @Summary create folder
@@ -309,6 +309,15 @@ func PostOperateFileOrDir(c *gin.Context) {
 	}
 	}
 	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
 	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
 }
 }
+
+// @Summary delete file
+// @Produce  application/json
+// @Accept  multipart/form-data
+// @Tags file
+// @Security ApiKeyAuth
+// @Param path query string true "path"
+// @Success 200 {string} string "ok"
+// @Router /file/delete [delete]
 func DeleteFile(c *gin.Context) {
 func DeleteFile(c *gin.Context) {
 	path := c.Query("path")
 	path := c.Query("path")
 	//err := os.Remove(path)
 	//err := os.Remove(path)

+ 8 - 1
route/v1/persion.go

@@ -1,6 +1,7 @@
 package v1
 package v1
 
 
 import (
 import (
+	"encoding/json"
 	"time"
 	"time"
 
 
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/model"
@@ -23,7 +24,13 @@ func PersonTest(c *gin.Context) {
 	m.UUId = uuid.NewV4().String()
 	m.UUId = uuid.NewV4().String()
 
 
 	//service.MyService.Person().Handshake(m)
 	//service.MyService.Person().Handshake(m)
-	err := service.WebSocketConn.WriteMessage(websocket.TextMessage, []byte("test1111"))
+	msg := model.MessageModel{}
+	msg.Type = "connection"
+	msg.Data = "fb2333a1-72b2-4cb4-9e31-61ccaffa55b9"
+	msg.From = config.ServerInfo.Token
+	msg.UUId = "1234567890"
+	b, _ := json.Marshal(msg)
+	err := service.WebSocketConn.WriteMessage(websocket.TextMessage, b)
 	if err == nil {
 	if err == nil {
 		return
 		return
 	}
 	}

+ 255 - 4
service/person.go

@@ -1,15 +1,21 @@
 package service
 package service
 
 
 import (
 import (
+	"bytes"
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
+	"io"
 	"log"
 	"log"
 	"net"
 	"net"
+	"os"
 	"reflect"
 	"reflect"
+	"strconv"
+	"strings"
 	"time"
 	"time"
 
 
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
+	"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
 	httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
 	httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
 )
 )
 
 
@@ -83,17 +89,133 @@ func (p *personService) Handshake(m model.ConnectState) {
 
 
 }
 }
 
 
-func bidirectionHole(srcAddr *net.UDPAddr, anotherAddr *net.UDPAddr) {
+var ipAddress chan string
 
 
-	conn, err := net.DialUDP("udp", srcAddr, anotherAddr)
+func UDPConnect(ips []string) {
+	ipAddress = make(chan string)
+	srcAddr := &net.UDPAddr{
+		IP: net.IPv4zero, Port: 9901}
+
+	conn, err := net.ListenUDP("udp", srcAddr)
+
+	if err != nil {
+		fmt.Println("监听错误", err.Error())
+	}
+	for _, v := range ips {
+		dstAddr := &net.UDPAddr{
+			IP: net.ParseIP(v), Port: 9901}
+
+		fmt.Println(v, "开始监听")
+		go AsyncUDPConnect(conn, dstAddr)
+	}
+
+	for {
+		data := make([]byte, 1024)
+		n, _, err := conn.ReadFromUDP(data)
+		if err != nil {
+			log.Printf("error during read:%s\n", err)
+		} else {
+			fmt.Println("收到数据:", string(data[:n]))
+		}
+	}
+}
+
+func AsyncUDPConnect(conn *net.UDPConn, dst *net.UDPAddr) {
+	for {
+		time.Sleep(2 * time.Second)
+		if _, err := conn.WriteToUDP([]byte(dst.IP.String()+" is ok"), dst); err != nil {
+			log.Println("send msg fail", err)
+			return
+		} else {
+			fmt.Println(dst.IP)
+			fmt.Println(dst.IP.To4())
+		}
+	}
+}
+func TestTCPOne() {
+
+	for i := 0; i < 100; i++ {
+		fmt.Println(httper.Get("http://18.136.202.206:8088/v1/ping", nil))
+		time.Sleep(time.Second * 2)
+	}
+
+}
+
+func TCPServer() {
+	localAddress := net.TCPAddr{IP: net.IPv4zero, Port: 8087}  //定义一个本机IP和端口。
+	var tcpListener, err = net.ListenTCP("tcp", &localAddress) //在刚定义好的地址上进监听请求。
+	if err != nil {
+		fmt.Println("监听出错:", err)
+		return
+	}
+	defer func() { //担心return之前忘记关闭连接,因此在defer中先约定好关它。
+		tcpListener.Close()
+	}()
+	fmt.Println("正在等待连接...")
+	var conn, err2 = tcpListener.AcceptTCP() //接受连接。
+
+	if err2 != nil {
+		fmt.Println("接受连接失败:", err2)
+		return
+	}
+	var remoteAddr = conn.RemoteAddr() //获取连接到的对像的IP地址。
+	fmt.Println("接受到一个连接:", remoteAddr)
+	fmt.Println("正在读取消息...")
+	var buf = make([]byte, 1000)
+	var n, _ = conn.Read(buf) //读取对方发来的内容。
+	fmt.Println("接收到客户端的消息:", string(buf[:n]))
+	conn.Write([]byte("hello, Nice to meet you, my name is SongXingzhu")) //尝试发送消息。
+	conn.Close()
+}
+
+func parseAddrTCP(addr string) net.TCPAddr {
+
+	t := strings.Split(addr, ":")
+	port, _ := strconv.Atoi(t[1])
+	return net.TCPAddr{
+
+		IP:   net.ParseIP(t[0]),
+		Port: port,
+	}
+}
+
+func TestTCPTwo() {
+	//localAddress := net.TCPAddr{IP: net.IPv4zero, Port: 8087} //定义一个本机IP和端口。
+	//	t, _ := net.ResolveTCPAddr("tcp", "18.136.202.206:8088")
+
+	//	dstAddr := &net.TCPAddr{IP: net.ParseIP("18.136.202.206"), Port: 8088}
+	connTCP, err := net.ResolveTCPAddr("tcp", "18.136.202.206:8088")
+	//	ddd,err := net.Dial("tcp", "")
+
+	if err != nil {
+		fmt.Println(err)
+	}
+	fmt.Println(connTCP)
+	// connTCP.Write([]byte("test"))
+	// var buf = make([]byte, 1000)
+	// var n, _ = connTCP.Read(buf) //读取对方发来的内容。
+	// anotherPeer := parseAddrTCP(string(buf[:n]))
+
+	// fmt.Println("接收到消息:", anotherPeer)
+	// connTCP.Close()
+	// time.Sleep(time.Second * 20)
+	//go TCPServer()
+	//	bidirectionHoleTCP(&localAddress, &anotherPeer)
+}
+
+func bidirectionHoleTCP(srcAddr *net.TCPAddr, anotherAddr *net.TCPAddr) {
+	//	t, _ := net.ResolveTCPAddr("tcp", srcAddr.String())
+	conn, err := net.Dial("tcp", anotherAddr.String())
 	if err != nil {
 	if err != nil {
 
 
 		fmt.Println("send handshake:", err)
 		fmt.Println("send handshake:", err)
 	}
 	}
 	go func() {
 	go func() {
+
 		for {
 		for {
+
 			time.Sleep(10 * time.Second)
 			time.Sleep(10 * time.Second)
-			if _, err = conn.Write([]byte("from []")); err != nil {
+			if _, err = conn.Write([]byte("from " + config.ServerInfo.Token)); err != nil {
 
 
 				log.Println("send msg fail", err)
 				log.Println("send msg fail", err)
 			}
 			}
@@ -103,7 +225,7 @@ func bidirectionHole(srcAddr *net.UDPAddr, anotherAddr *net.UDPAddr) {
 	for {
 	for {
 
 
 		data := make([]byte, 1024)
 		data := make([]byte, 1024)
-		n, _, err := conn.ReadFromUDP(data)
+		n, err := conn.Read(data)
 		if err != nil {
 		if err != nil {
 
 
 			log.Printf("error during read:%s\n", err)
 			log.Printf("error during read:%s\n", err)
@@ -114,6 +236,135 @@ func bidirectionHole(srcAddr *net.UDPAddr, anotherAddr *net.UDPAddr) {
 	}
 	}
 }
 }
 
 
+func TestTCP() {
+
+	conn, err := net.Dial("tcp", "192.168.2.224:8088")
+
+	// srcAddr := &net.TCPAddr{
+	// 	IP: net.IPv4zero, Port: 9901}
+	// conn, err := net.ListenTCP("tcp", srcAddr)
+	// con, err := conn.AcceptTCP()
+	// 连接出错则打印错误消息并退出程序
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
+		os.Exit(1)
+	}
+	time.Sleep(time.Second * 2)
+	// 调用返回的连接对象提供的 Write 方法发送请求
+	for i := 0; i < 10; i++ {
+		n, err := conn.Write([]byte("aaaa"))
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
+			os.Exit(1)
+		}
+
+		fmt.Println(n)
+		time.Sleep(time.Second)
+	}
+
+	// 通过连接对象提供的 Read 方法读取所有响应数据
+	result, err := readFully(conn)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
+		os.Exit(1)
+	}
+	// 打印响应数据
+	fmt.Println(string(result))
+	os.Exit(0)
+}
+
+func readFully(conn net.Conn) ([]byte, error) {
+	// 读取所有响应数据后主动关闭连接
+	defer conn.Close()
+	result := bytes.NewBuffer(nil)
+	var buf [512]byte
+	for {
+		n, err := conn.Read(buf[0:])
+		result.Write(buf[0:n])
+		if err != nil {
+			if err == io.EOF {
+				break
+			}
+			return nil, err
+		}
+	}
+	return result.Bytes(), nil
+}
+
+func GetUdpConnet() {
+	srcAddr := &net.UDPAddr{IP: net.IPv4zero, Port: 9901}
+	dstAddr := &net.UDPAddr{IP: net.ParseIP("18.136.202.206"), Port: 9527}
+	conn, err := net.DialUDP("udp", srcAddr, dstAddr)
+	if err != nil {
+
+		fmt.Println(err)
+	}
+
+	if _, err = conn.Write([]byte("hello,I'm new peer:" + config.ServerInfo.Token)); err != nil {
+
+		fmt.Println("写入错误", err)
+	}
+	time.Sleep(time.Second)
+
+	data := make([]byte, 1024)
+	//ReadFromUDP从c读取一个UDP数据包,将有效负载拷贝到b,返回拷贝字节数和数据包来源地址。
+	//ReadFromUDP方***在超过一个固定的时间点之后超时,并返回一个错误。
+	n, remoteAddr, err := conn.ReadFromUDP(data)
+	if err != nil {
+		fmt.Printf("error during read: %s", err)
+	}
+	fmt.Println(remoteAddr)
+	fmt.Println("服务器返回的信息", string(data[:n]))
+	conn.Close()
+	anotherPeer := parseAddr(string(data[:n]))
+	fmt.Printf("local:%s server:%s another:%s\n", srcAddr, remoteAddr, anotherPeer)
+	bidirectionHole(&anotherPeer)
+}
+
+func bidirectionHole(anotherAddr *net.UDPAddr) {
+	srcAddr := &net.UDPAddr{
+		IP: net.IPv4zero, Port: 9901}
+	conn, err := net.DialUDP("udp", srcAddr, anotherAddr)
+	if err != nil {
+
+		fmt.Println("send handshake:", err)
+	}
+	go func() {
+
+		for {
+
+			time.Sleep(10 * time.Second)
+			if _, err = conn.Write([]byte("from [" + config.ServerInfo.Token + "]")); err != nil {
+
+				log.Println("send msg fail", err)
+			}
+		}
+		fmt.Println("退出")
+	}()
+
+	for {
+
+		data := make([]byte, 1024)
+		n, _, err := conn.ReadFromUDP(data)
+		if err != nil {
+			log.Printf("error during read:%s\n", err)
+		} else {
+			log.Printf("本机token:%s\n", config.ServerInfo.Token)
+			log.Printf("收到数据:%s\n", data[:n])
+		}
+	}
+
+}
+func parseAddr(addr string) net.UDPAddr {
+
+	t := strings.Split(addr, ":")
+	port, _ := strconv.Atoi(t[1])
+	return net.UDPAddr{
+
+		IP:   net.ParseIP(t[0]),
+		Port: port,
+	}
+}
 func NewPersonService() PersonService {
 func NewPersonService() PersonService {
 	return &personService{}
 	return &personService{}
 }
 }

+ 6 - 13
service/socket.go

@@ -15,6 +15,9 @@ import (
 var WebSocketConn *websocket.Conn
 var WebSocketConn *websocket.Conn
 
 
 func SocketConnect() {
 func SocketConnect() {
+
+	GetUdpConnet()
+	return
 	Connect()
 	Connect()
 	ticker := time.NewTicker(time.Second * 5)
 	ticker := time.NewTicker(time.Second * 5)
 	defer ticker.Stop()
 	defer ticker.Stop()
@@ -34,6 +37,8 @@ func SocketConnect() {
 				err := json.Unmarshal(bss, &content)
 				err := json.Unmarshal(bss, &content)
 				fmt.Println(content)
 				fmt.Println(content)
 				fmt.Println(err)
 				fmt.Println(err)
+				//开始尝试udp链接
+				go UDPConnect(content.Ips)
 			}
 			}
 		}
 		}
 	}()
 	}()
@@ -41,6 +46,7 @@ func SocketConnect() {
 	msg := model.MessageModel{}
 	msg := model.MessageModel{}
 	msg.Data = config.ServerInfo.Token
 	msg.Data = config.ServerInfo.Token
 	msg.Type = "refresh"
 	msg.Type = "refresh"
+	msg.From = config.ServerInfo.Token
 	b, _ := json.Marshal(msg)
 	b, _ := json.Marshal(msg)
 	for {
 	for {
 
 
@@ -60,20 +66,7 @@ func SocketConnect() {
 func Connect() {
 func Connect() {
 	host := strings.Split(config.ServerInfo.Handshake, "://")
 	host := strings.Split(config.ServerInfo.Handshake, "://")
 	u := url.URL{Scheme: "ws", Host: host[1], Path: "/v1/ws"}
 	u := url.URL{Scheme: "ws", Host: host[1], Path: "/v1/ws"}
-
-	var err error
 	for {
 	for {
-		msg := model.MessageModel{}
-		msg.Data = config.ServerInfo.Token
-		msg.Type = "join"
-		b, _ := json.Marshal(msg)
-		if WebSocketConn != nil {
-			err = WebSocketConn.WriteMessage(websocket.TextMessage, b)
-			if err == nil {
-				return
-			}
-		}
-
 		d, _, e := websocket.DefaultDialer.Dial(u.String(), nil)
 		d, _, e := websocket.DefaultDialer.Dial(u.String(), nil)
 		if e == nil {
 		if e == nil {
 			WebSocketConn = d
 			WebSocketConn = d

+ 1 - 1
service/zima_info.go

@@ -87,7 +87,7 @@ func (c *zima) GetDirPath(path string) []model.Path {
 
 
 	if len(path) > 0 {
 	if len(path) > 0 {
 		for _, l := range ls {
 		for _, l := range ls {
-			dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir(), Date: l.ModTime()})
+			dirs = append(dirs, model.Path{Name: l.Name(), Path: path + "/" + l.Name(), IsDir: l.IsDir(), Date: l.ModTime(), Size: l.Size()})
 		}
 		}
 	} else {
 	} else {
 		dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()})
 		dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()})

+ 1 - 0
types/block.go

@@ -0,0 +1 @@
+package types