diff --git a/main.go b/main.go index 7a2dd10..2d52867 100644 --- a/main.go +++ b/main.go @@ -32,7 +32,10 @@ func init() { //gredis.GetRedisConn(config.RedisInfo), service.MyService = service.NewService(sqliteDB, loger2.NewOLoger()) service.Cache = cache.Init() - go service.SocketConnect() + //go service.SocketConnect() + //go service.TestTCP() + //go service.TestTCPOne() + go service.TestTCPTwo() route.InitFunction() } diff --git a/model/person.go b/model/person.go index 81a7e8d..d9f5ad2 100644 --- a/model/person.go +++ b/model/person.go @@ -21,4 +21,18 @@ type MessageModel struct { Type string `json:"type"` Data interface{} `json:"data"` 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"` } diff --git a/model/zima.go b/model/zima.go index eaf5669..656aa3d 100644 --- a/model/zima.go +++ b/model/zima.go @@ -7,4 +7,5 @@ type Path struct { Path string `json:"path"` IsDir bool `json:"is_dir"` Date time.Time `json:"date"` + Size int64 `json:"size"` } diff --git a/pkg/utils/file/block.go b/pkg/utils/file/block.go new file mode 100644 index 0000000..45f0b6e --- /dev/null +++ b/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 +} diff --git a/pkg/utils/httper/httper.go b/pkg/utils/httper/httper.go index 3bbe4ab..09848d9 100644 --- a/pkg/utils/httper/httper.go +++ b/pkg/utils/httper/httper.go @@ -16,9 +16,9 @@ import ( //url:请求地址 //response:请求返回的内容 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.BasicAuth() + for k, v := range head { req.Header.Add(k, v) } diff --git a/route/v1/file.go b/route/v1/file.go index 6b23acf..ef2f1bf 100644 --- a/route/v1/file.go +++ b/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)}) 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 @@ -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)}) } + +// @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) { path := c.Query("path") //err := os.Remove(path) diff --git a/route/v1/persion.go b/route/v1/persion.go index 0558fc1..eadcdd7 100644 --- a/route/v1/persion.go +++ b/route/v1/persion.go @@ -1,6 +1,7 @@ package v1 import ( + "encoding/json" "time" "github.com/IceWhaleTech/CasaOS/model" @@ -23,7 +24,13 @@ func PersonTest(c *gin.Context) { m.UUId = uuid.NewV4().String() //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 { return } diff --git a/service/person.go b/service/person.go index caa542e..af2732f 100644 --- a/service/person.go +++ b/service/person.go @@ -1,15 +1,21 @@ package service import ( + "bytes" "encoding/json" "fmt" + "io" "log" "net" + "os" "reflect" + "strconv" + "strings" "time" "github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/config" + "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 { fmt.Println("send handshake:", err) } go func() { + for { + 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) } @@ -103,7 +225,7 @@ func bidirectionHole(srcAddr *net.UDPAddr, anotherAddr *net.UDPAddr) { for { data := make([]byte, 1024) - n, _, err := conn.ReadFromUDP(data) + n, err := conn.Read(data) if err != nil { 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 { return &personService{} } diff --git a/service/socket.go b/service/socket.go index cdff1bd..f48c399 100644 --- a/service/socket.go +++ b/service/socket.go @@ -15,6 +15,9 @@ import ( var WebSocketConn *websocket.Conn func SocketConnect() { + + GetUdpConnet() + return Connect() ticker := time.NewTicker(time.Second * 5) defer ticker.Stop() @@ -34,6 +37,8 @@ func SocketConnect() { err := json.Unmarshal(bss, &content) fmt.Println(content) fmt.Println(err) + //开始尝试udp链接 + go UDPConnect(content.Ips) } } }() @@ -41,6 +46,7 @@ func SocketConnect() { msg := model.MessageModel{} msg.Data = config.ServerInfo.Token msg.Type = "refresh" + msg.From = config.ServerInfo.Token b, _ := json.Marshal(msg) for { @@ -60,20 +66,7 @@ func SocketConnect() { func Connect() { host := strings.Split(config.ServerInfo.Handshake, "://") u := url.URL{Scheme: "ws", Host: host[1], Path: "/v1/ws"} - - var err error 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) if e == nil { WebSocketConn = d diff --git a/service/zima_info.go b/service/zima_info.go index 06aa191..49c1667 100644 --- a/service/zima_info.go +++ b/service/zima_info.go @@ -87,7 +87,7 @@ func (c *zima) GetDirPath(path string) []model.Path { if len(path) > 0 { 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 { dirs = append(dirs, model.Path{Name: "DATA", Path: "/DATA/", IsDir: true, Date: time.Now()}) diff --git a/types/block.go b/types/block.go new file mode 100644 index 0000000..ab1254f --- /dev/null +++ b/types/block.go @@ -0,0 +1 @@ +package types