Parcourir la source

prepare for test

link il y a 3 ans
Parent
commit
9796c5aad7

+ 4 - 0
conf/conf.ini.sample

@@ -9,6 +9,7 @@ DateTimeFormat = 2006-01-02 15:04:05
 TimeFormat = 15:04:05
 DateFormat = 2006-01-02
 ProjectPath = /casaOS/server
+RootPath = /casaOS
 
 
 [server]
@@ -44,3 +45,6 @@ ConfigStr =
 WidgetList =
 Analyse =
 
+[file]
+ShareDir =
+DownloadDir = /DATA

+ 9 - 3
main.go

@@ -6,6 +6,7 @@ import (
 	"net/http"
 	"time"
 
+	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/cache"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
@@ -32,9 +33,14 @@ func init() {
 	//gredis.GetRedisConn(config.RedisInfo),
 	service.MyService = service.NewService(sqliteDB, loger2.NewOLoger())
 	service.Cache = cache.Init()
-	//go service.UDPConnect([]string{})
-	go service.SocketConnect()
-	//go service.UDPService()
+
+	go service.UDPService()
+
+	go service.UDPConnect([]string{})
+	service.Summary = make(map[string]model.FileSummaryModel)
+	service.UDPAddressMap = make(map[string]string)
+	//go service.SocketConnect()
+
 	route.InitFunction()
 
 }

+ 0 - 1
model/person.go

@@ -40,7 +40,6 @@ type FileDetailModel struct {
 type FileSummaryModel struct {
 	Hash      string `json:"hash"` //Verify file
 	Name      string `json:"name"`
-	Path      string `json:"path"`
 	BlockSize int    `json:"block_size"`
 	Length    int    `json:"length"`
 	Size      int64  `json:"size"`

+ 6 - 0
model/sys_common.go

@@ -39,6 +39,7 @@ type APPModel struct {
 	TimeFormat     string
 	DateFormat     string
 	ProjectPath    string
+	RootPath       string
 }
 
 //公共返回模型
@@ -76,3 +77,8 @@ type SystemConfig struct {
 type CasaOSGlobalVariables struct {
 	AppChange bool
 }
+
+type FileSetting struct {
+	ShareDir    []string `json:"share_dir" delim:"|"`
+	DownloadDir string   `json:"download_dir"`
+}

+ 3 - 0
pkg/config/init.go

@@ -35,6 +35,8 @@ var SystemConfigInfo = &model.SystemConfig{}
 
 var CasaOSGlobalVariables = &model.CasaOSGlobalVariables{}
 
+var FileSettingInfo = &model.FileSetting{}
+
 var Cfg *ini.File
 
 //初始化设置,获取系统的部分信息。
@@ -58,6 +60,7 @@ func InitSetup(config string) {
 	mapTo("redis", RedisInfo)
 	mapTo("server", ServerInfo)
 	mapTo("system", SystemConfigInfo)
+	mapTo("file", FileSettingInfo)
 	SystemConfigInfo.ConfigPath = configDir
 	//	AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
 

+ 2 - 2
pkg/utils/file/block.go

@@ -60,9 +60,9 @@ func ComparisonHash(data []byte, hash string) bool {
 
 //get prefix byte length
 func PrefixLength(byteLength int) []byte {
-	lengthByte := []byte{'0', '0', '0', '0'}
+	lengthByte := []byte{'0', '0', '0', '0', '0', '0'}
 	bSize := strconv.Itoa(byteLength)
-	cha := 4 - len(bSize)
+	cha := 6 - len(bSize)
 	for i := len(bSize); i > 0; i-- {
 		lengthByte[cha+i-1] = bSize[i-1]
 	}

+ 15 - 2
route/init.go

@@ -25,7 +25,7 @@ func InitFunction() {
 	Update2_3()
 	CheckSerialDiskMount()
 
-	CheckToken2_9()
+	CheckToken2_11()
 
 }
 
@@ -236,11 +236,24 @@ func CheckSerialDiskMount() {
 func Update2_3() {
 	command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh")
 }
-func CheckToken2_9() {
+func CheckToken2_11() {
 	if len(config.ServerInfo.Token) == 0 {
 		token := uuid.NewV4().String
 		config.ServerInfo.Token = token()
 		config.Cfg.Section("server").Key("Token").SetValue(token())
 		config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
 	}
+	if len(config.AppInfo.RootPath) == 0 {
+		config.Cfg.Section("app").Key("RootPath").SetValue("/casaOS")
+		config.AppInfo.RootPath = "/casaOS"
+		config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
+	}
+	// str := []string{}
+	// str = append(str, "ddd")
+	// str = append(str, "aaa")
+	// ddd := strings.Join(str, "|")
+	// config.Cfg.Section("file").Key("ShareDir").SetValue(ddd)
+
+	// config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
+
 }

+ 5 - 4
route/route.go

@@ -290,13 +290,14 @@ func InitRouter() *gin.Engine {
 		v1PersonGroup := v1Group.Group("/persion")
 		v1PersonGroup.Use()
 		{
-			// v1PersonGroup.GET("/test", v1.PersonTest)
+			v1PersonGroup.GET("/test", v1.PersonTest)
 			v1PersonGroup.GET("/users", v1.GetPersionFriend)        //用户列表
 			v1PersonGroup.POST("/user", v1.PostAddPersionFriend)    //添加用户
 			v1PersonGroup.GET("/directory", v1.GetPersionDirectory) //文件列表
-			//v1PersonGroup.GET("/download", v1.GetPersionFile)       //下载文件
-			v1PersonGroup.PUT("/edit/:token", v1.PutPersionNick)  //修改好友
-			v1PersonGroup.GET("/list", v1.GetPersionDownloadList) //下载列表(需要考虑试试下载速度)
+			v1PersonGroup.GET("/file", v1.GetPersionFile)           //下载文件
+			v1PersonGroup.PUT("/edit/:token", v1.PutPersionNick)    //修改好友
+			v1PersonGroup.GET("/list", v1.GetPersionDownloadList)   //下载列表(需要考虑试试下载速度)
+			v1PersonGroup.DELETE("/file/id", v1.DeletePersionDownloadFile)
 			// v1PersonGroup.PUT("/state/:id", v1.PutPersionCancelDownload) //修改下载状态(开始暂停删除)
 
 		}

+ 82 - 43
route/v1/persion.go

@@ -4,7 +4,6 @@ import (
 	"encoding/json"
 	"fmt"
 	"net/http"
-	"time"
 
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
@@ -13,48 +12,48 @@ import (
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
 	"github.com/IceWhaleTech/CasaOS/types"
 	"github.com/gin-gonic/gin"
-	"github.com/gorilla/websocket"
 	uuid "github.com/satori/go.uuid"
 )
 
 func PersonTest(c *gin.Context) {
 
+	token := c.Query("token")
 	//service.MyService.Person().GetPersionInfo("fb2333a1-72b2-4cb4-9e31-61ccaffa55b9")
 
-	m := model.ConnectState{}
-	m.CreatedAt = time.Now()
-	m.From = config.ServerInfo.Token
-	m.To = "fb2333a1-72b2-4cb4-9e31-61ccaffa55b9"
-	m.Type = ""
-	m.UUId = uuid.NewV4().String()
-
-	//service.MyService.Person().Handshake(m)
 	msg := model.MessageModel{}
-	msg.Type = "connection"
-	msg.Data = "fb2333a1-72b2-4cb4-9e31-61ccaffa55b9"
+	msg.Type = "hello"
+	msg.Data = ""
 	msg.From = config.ServerInfo.Token
-	msg.UUId = "1234567890"
-	b, _ := json.Marshal(msg)
-	err := service.WebSocketConn.WriteMessage(websocket.TextMessage, b)
+	msg.To = token
+	msg.UUId = uuid.NewV4().String()
+
+	dd, err := service.Dial("", msg)
 	if err == nil {
-		return
+		fmt.Println(err)
 	}
+	fmt.Println(dd)
+	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
 }
 
-//get other persion file
+// @Summary add friend
+// @Produce  application/json
+// @Accept application/json
+// @Tags persion
+// @Param  token formData int true "Opponent token"
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /persion/file/{id} [delete]
 func GetPersionFile(c *gin.Context) {
+
 	path := c.Query("path")
-	persion := c.Query("persion")
-	if len(path) == 0 && len(persion) == 0 {
+	token := c.Query("token")
+	if len(path) == 0 && len(token) == 0 {
 		c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
 		return
 	}
 	//任务标识
 	uuid := uuid.NewV4().String()
 
-	//1.通知对方需要下载
-	service.MyService.Person().GetFileDetail(uuid, path, persion)
-
 	//2.添加数据库
 
 	task := model2.PersionDownloadDBModel{}
@@ -63,28 +62,59 @@ func GetPersionFile(c *gin.Context) {
 	task.Length = 0
 	task.Size = 0
 	task.State = types.DOWNLOADAWAIT
-	task.TempPath = ""
 	task.Type = 0
-	service.MyService.Person().AddDownloadTask(task)
+	service.MyService.Download().AddDownloadTask(task)
+
+	m := model.MessageModel{}
+	m.Data = path
+	m.From = config.ServerInfo.Token
+	m.To = token
+	m.Type = "file_data"
+	m.UUId = uuid
+	_, err := service.Dial("192.168.2.224:9902", m)
+	if err != nil {
+		fmt.Println(err)
+	}
 
 	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
 }
-func GetPersionDownloadList(c *gin.Context) {
-	path := c.Query("path")
-	persion := c.Query("persion")
-	if len(path) == 0 && len(persion) == 0 {
+
+// @Summary delete download file records
+// @Produce  application/json
+// @Accept application/json
+// @Tags persion
+// @Param  token formData int true "Opponent token"
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /persion/file/{id} [delete]
+func DeletePersionDownloadFile(c *gin.Context) {
+
+	id := c.Param("id")
+	if len(id) == 0 {
 		c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
 		return
 	}
-	//任务标识
-	uuid := uuid.NewV4().String()
 
-	//1.通知对方需要下载
-	service.MyService.Person().GetFileDetail(uuid, path, persion)
+	service.MyService.Download().DelDownload(id)
 
 	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
 }
 
+// @Summary get file download list
+// @Produce  application/json
+// @Accept application/json
+// @Tags persion
+// @Param  state query int true "wait:1,loading:1,pause:2,finish:3,error:4" Enums(0,1,2,4)
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /persion/list [get]
+func GetPersionDownloadList(c *gin.Context) {
+	state := c.DefaultQuery("state", "")
+	list := service.MyService.Download().GetDownloadListByState(state)
+
+	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
+}
+
 // @Summary add friend
 // @Produce  application/json
 // @Accept application/json
@@ -92,7 +122,7 @@ func GetPersionDownloadList(c *gin.Context) {
 // @Param  token formData int true "Opponent token"
 // @Security ApiKeyAuth
 // @Success 200 {string} string "ok"
-// @Router /persion/edit [put]
+// @Router /persion/edit/{token} [put]
 func PutPersionNick(c *gin.Context) {
 	token := c.Param("token")
 	nick := c.PostForm("nick")
@@ -107,7 +137,7 @@ func PutPersionNick(c *gin.Context) {
 	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
 }
 
-// @Summary add friend
+// @Summary get friends list
 // @Produce  application/json
 // @Accept application/json
 // @Tags persion
@@ -134,15 +164,16 @@ func PostAddPersionFriend(c *gin.Context) {
 		c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
 		return
 	}
-	//step:远程验证token是否存在
+
 	msg := model.MessageModel{}
-	msg.Type = types.PERSONADDFRIEND
-	msg.To = token
+	msg.Type = "connection"
 	msg.Data = token
 	msg.From = config.ServerInfo.Token
+	msg.To = token
 	msg.UUId = uuid.NewV4().String()
-	b, _ := json.Marshal(msg)
-	err := service.WebSocketConn.WriteMessage(websocket.TextMessage, b)
+
+	_, err := service.Dial("", msg)
+
 	fmt.Println(err)
 
 	friend := model2.FriendModel{}
@@ -151,10 +182,18 @@ func PostAddPersionFriend(c *gin.Context) {
 	c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
 }
 
+// @Summary get directory list
+// @Produce  application/json
+// @Accept application/json
+// @Tags persion
+// @Param  token query int true "Opponent token"
+// @Security ApiKeyAuth
+// @Success 200 {string} string "ok"
+// @Router /persion/directory [get]
 func GetPersionDirectory(c *gin.Context) {
 	path := c.Query("path")
-	persion := c.Query("persion")
-	if len(path) == 0 && len(persion) == 0 {
+	token := c.Query("token")
+	if len(path) == 0 && len(token) == 0 {
 		c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
 		return
 	}
@@ -163,10 +202,10 @@ func GetPersionDirectory(c *gin.Context) {
 	m := model.MessageModel{}
 	m.Data = path
 	m.From = config.ServerInfo.Token
-	m.To = persion
+	m.To = token
 	m.Type = "directory"
 	m.UUId = uuid
-	result, err := service.Dial("192.168.2.225:9902", m)
+	result, err := service.Dial(service.UDPAddressMap[token], m)
 	if err != nil {
 		fmt.Println(err)
 	}

+ 52 - 0
service/download.go

@@ -0,0 +1,52 @@
+package service
+
+import (
+	model2 "github.com/IceWhaleTech/CasaOS/service/model"
+	"gorm.io/gorm"
+)
+
+type DownloadService interface {
+	AddDownloadTask(m model2.PersionDownloadDBModel)   //添加下载任务
+	EditDownloadState(m model2.PersionDownloadDBModel) //只修改状态
+	SaveDownload(m model2.PersionDownloadDBModel)
+	DelDownload(uuid string)
+	GetDownloadById(uuid string) model2.PersionDownloadDBModel
+	GetDownloadListByState(state string) []model2.PersionDownloadDBModel
+}
+type downloadService struct {
+	db *gorm.DB
+}
+
+func (d *downloadService) AddDownloadTask(m model2.PersionDownloadDBModel) {
+	d.db.Create(&m)
+}
+func (d *downloadService) EditDownloadState(m model2.PersionDownloadDBModel) {
+	d.db.Model(&m).Where("uuid = ?", m.UUID).Update("state", m.State)
+}
+
+func (d *downloadService) DelDownload(uuid string) {
+	var m model2.PersionDownloadDBModel
+	d.db.Where("uuid = ?", uuid).Delete(&m)
+}
+func (d *downloadService) GetDownloadById(uuid string) model2.PersionDownloadDBModel {
+	var m model2.PersionDownloadDBModel
+	d.db.Model(m).Where("uuid = ?", uuid).First(&m)
+	return m
+}
+func (d *downloadService) GetDownloadListByState(state string) (list []model2.PersionDownloadDBModel) {
+	if len(state) == 0 {
+		d.db.Find(&list)
+
+	} else {
+		d.db.Where("state = ?", state).Find(&list)
+	}
+
+	return
+}
+
+func (d *downloadService) SaveDownload(m model2.PersionDownloadDBModel) {
+	d.db.Save(&m)
+}
+func NewDownloadService(db *gorm.DB) DownloadService {
+	return &downloadService{db: db}
+}

+ 14 - 0
service/friend.go

@@ -1,6 +1,8 @@
 package service
 
 import (
+	"reflect"
+
 	model2 "github.com/IceWhaleTech/CasaOS/service/model"
 	"gorm.io/gorm"
 )
@@ -12,6 +14,7 @@ type FriendService interface {
 	GetFriendById(m model2.FriendModel) model2.FriendModel
 	GetFriendList() (list []model2.FriendModel)
 	UpdateAddFriendType(m model2.FriendModel)
+	UpdateOrCreate(m model2.FriendModel)
 }
 
 type friendService struct {
@@ -38,6 +41,17 @@ func (p *friendService) GetFriendList() (list []model2.FriendModel) {
 	return list
 }
 
+func (p *friendService) UpdateOrCreate(m model2.FriendModel) {
+	friend := model2.FriendModel{}
+	p.db.Where("token = ?", m.Token).First(&friend)
+	if reflect.DeepEqual(friend, model2.FriendModel{}) {
+		p.db.Create(&m)
+	} else {
+		p.db.Model(&m).Updates(m)
+	}
+
+}
+
 func (p *friendService) UpdateAddFriendType(m model2.FriendModel) {
 	p.db.Model(&m).Updates(m)
 }

+ 7 - 13
service/model/o_download.go

@@ -2,23 +2,17 @@ package model
 
 type PersionDownloadDBModel struct {
 	UUID      string `gorm:"column:uuid;primary_key" json:"uuid"`
-	State     int    `json:"state"`     //
-	Type      int    `json:"type"`      //defult 1
-	Name      string `json:"name"`      //file name
-	TempPath  string `json:"temp_path"` //temp path
-	Size      int64  `json:"size"`      //file size
-	Section   string `json:"section"`
+	State     int    `json:"state"` //
+	Type      int    `json:"type"`  //defult 1
+	Name      string `json:"name"`  //file name
+	Size      int64  `json:"size"`  //file size
+	BlockSize int    `json:"block_size"`
 	Length    int    `json:"length"` //slice length
 	Hash      string `json:"hash"`
-	CreatedAt string `gorm:"<-:create;autoCreateTime" json:"created_at"`
-	UpdatedAt string `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at"`
+	CreatedAt int64  `gorm:"autoCreateTime" json:"created_at"`
+	UpdatedAt int64  `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"`
 }
 
 func (p *PersionDownloadDBModel) TableName() string {
 	return "o_persion_download"
 }
-
-type PersionFileSectionModel struct {
-	Index int    `json:"index"`
-	Hash  string `json:"hash"`
-}

+ 2 - 2
service/model/o_friend.go

@@ -2,8 +2,8 @@ package model
 
 type FriendModel struct {
 	State     int    `json:"state"` //备用
-	CreatedAt string `gorm:"<-:create;autoCreateTime" json:"created_at"`
-	UpdatedAt string `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at"`
+	CreatedAt int64  `gorm:"autoCreateTime" json:"created_at"`
+	UpdatedAt int64  `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"`
 	NickName  string `json:"nick_name"` //custom name
 	Avatar    string `json:"avatar"`    //头像
 	Name      string `json:"name"`

+ 84 - 159
service/person.go

@@ -40,14 +40,6 @@ type PersonService interface {
 	ReplyGetFileDetail(m model.MessageModel)
 	ReceiveFileData(m model.MessageModel)
 	ReceiveGetFileDetail(m model.MessageModel)
-
-	//------------ database
-	AddDownloadTask(m model2.PersionDownloadDBModel)   //添加下载任务
-	EditDownloadState(m model2.PersionDownloadDBModel) //只修改状态
-	EditDownloading(m model2.PersionDownloadDBModel, section model2.PersionFileSectionModel)
-	SaveDownloadState(m model2.PersionDownloadDBModel)
-	DelDownload(uuid string)
-	GetDownloadById(uuid string) model2.PersionDownloadDBModel
 }
 
 type personService struct {
@@ -81,7 +73,7 @@ func (p *personService) Handshake(m model.ConnectState) {
 	//1先进行udp打通成功
 
 	srcAddr := &net.UDPAddr{
-		IP: net.IPv4zero, Port: 9901} //注意端口必须固定
+		IP: net.IPv4zero, Port: 9904} //注意端口必须固定
 	dstAddr := &net.UDPAddr{
 		IP: net.ParseIP(config.ServerInfo.Handshake), Port: 9527}
 	//DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"udp"、"udp4"、"udp6";如果laddr不是nil,将使用它作为本地地址,否则自动选择一个本地地址。
@@ -101,7 +93,6 @@ func (p *personService) Handshake(m model.ConnectState) {
 	if err != nil {
 		fmt.Printf("error during read: %s", err)
 	}
-	conn.Close()
 	toPersion := model.PersionModel{}
 	err = json.Unmarshal(data[:n], &toPersion)
 	if err != nil {
@@ -116,33 +107,6 @@ func (p *personService) Handshake(m model.ConnectState) {
 
 }
 
-func (p *personService) AddDownloadTask(m model2.PersionDownloadDBModel) {
-	p.db.Create(&m)
-}
-func (p *personService) EditDownloadState(m model2.PersionDownloadDBModel) {
-	p.db.Model(&m).Where("uuid = ?", m.UUID).Update("state", m.State)
-}
-
-func (p *personService) EditDownloading(m model2.PersionDownloadDBModel, section model2.PersionFileSectionModel) {
-	b, _ := json.Marshal(section)
-	m.Section = string(b)
-	p.db.Model(&m).Where("uuid = ?", m.UUID).Update("section", m.Section)
-}
-
-func (p *personService) DelDownload(uuid string) {
-	var m model2.PersionDownloadDBModel
-	p.db.Where("uuid = ?", uuid).Delete(&m)
-}
-func (p *personService) GetDownloadById(uuid string) model2.PersionDownloadDBModel {
-	var m model2.PersionDownloadDBModel
-	p.db.Model(m).Where("uuid = ?", uuid).First(&m)
-	return m
-}
-
-func (p *personService) SaveDownloadState(m model2.PersionDownloadDBModel) {
-	p.db.Save(&m)
-}
-
 var ipAddress chan string
 
 type sysConn struct {
@@ -152,104 +116,11 @@ type sysConn struct {
 }
 
 func UDPConnect(ips []string) {
-	quicConfig := &quic.Config{
-		ConnectionIDLength:    12,
-		HandshakeIdleTimeout:  time.Second * 8,
-		MaxIdleTimeout:        time.Second * 45,
-		MaxIncomingStreams:    32,
-		MaxIncomingUniStreams: -1,
-		KeepAlive:             true,
-	}
-	fmt.Println(quicConfig)
-	//PersonUDPMap = make(map[string]*net.UDPAddr)
-	ipAddress = make(chan string)
-
-	srcAddr := &net.UDPAddr{
-		IP: net.IPv4zero, Port: 9901}
-	fmt.Println(srcAddr)
-	//UDPconn, err := net.ListenUDP("udp", srcAddr)
-	// sysconn := &sysConn{
-	// 	conn:   UDPconn,
-	// 	header: "",
-	// 	auth:   nil,
-	// }
-	// if err != nil {
-	// 	fmt.Println(err)
-	// }
-	// liste, err := quic.Listen(UDPconn, generateTLSConfig(), nil)
-	// if err != nil {
-	// 	fmt.Println(err)
-	// }
-	// ssss, err := liste.Accept(context.Background())
-	// if err != nil {
-	// 	fmt.Println(err)
-	// }
-	// st, err := ssss.AcceptStream(context.Background())
-	// if err != nil {
-	// 	fmt.Println(err)
-	// }
-	// st.Write([]byte("ssss"))
-	qlister, err := quic.ListenAddr("0.0.0.0:9901", generateTLSConfig(), nil)
-	//qlister, err := quic.Listen(UDPconn, nil, nil)
-	if err != nil {
-		fmt.Println("quic错误", qlister)
-	}
-	//session, e := qlister.Accept()
-	sess, err := qlister.Accept(context.Background())
-	sess.SendMessage([]byte("aaaa"))
-	stream, err := sess.AcceptStream(context.Background())
-	stream.Write([]byte("bbb"))
-	//quic.Dial()
-	if err != nil {
-		fmt.Println("quic错误", qlister)
-	}
 
-	if err != nil {
-		fmt.Println("监听错误", err.Error())
-	}
-	for _, v := range ips {
-		dstAddr := &net.UDPAddr{
-			IP: net.ParseIP(v), Port: 9901}
-
-		fmt.Println(v, "开始监听")
-
-		//quic.Dial()
-
-		go AsyncUDPConnect(dstAddr)
-	}
-
-	for {
-		data := make([]byte, 1024)
-		n, add, err := UDPconn.ReadFromUDP(data)
-		fmt.Println(add)
-		if err != nil {
-			log.Printf("error during read:%s\n", err)
-		} else {
+	//m := model.ConnectState{}
 
-			fmt.Println("收到数据:", string(data[:n]))
-			msg := model.MessageModel{}
-			err := json.Unmarshal(data[:n], &msg)
-			if err != nil {
-				log.Printf("转义错误:%s\n", err)
-			}
-			//todo:检查数据库是否为合法请求
-			if msg.Type == "hi" {
-				//add ip
-				//PersonUDPMap[msg.From] = add
-			} else if msg.Type == "browse" {
-				//获取目录结构
-			} else if msg.Type == "file_detail" {
-				MyService.Person().ReplyGetFileDetail(msg)
-			} else if msg.Type == "file_detail_reply" {
-				MyService.Person().ReceiveGetFileDetail(msg)
-			} else if msg.Type == "file_data_reply" {
-				MyService.Person().ReceiveFileData(msg)
-			} else {
-				fmt.Println("未知事件")
-			}
+	//MyService.Person().Handshake(m)
 
-		}
-	}
 }
 
 // Setup a bare-bones TLS config for the server
@@ -327,7 +198,6 @@ func (p *personService) Download(m model.MessageModel) {
 	}
 	summary := model.FileSummaryModel{}
 	summary.Hash = file.GetHashByPath(fDetail.Name())
-	summary.Path = m.Data.(string)
 	summary.BlockSize, summary.Length = file.GetBlockInfo(fDetail.Size())
 
 	msg := model.MessageModel{}
@@ -349,7 +219,8 @@ func (p *personService) Download(m model.MessageModel) {
 
 //receive file data
 func (p *personService) ReceiveFileData(m model.MessageModel) {
-	task := p.GetDownloadById(m.UUId)
+	//task := p.GetDownloadById(m.UUId)
+	task := model2.PersionDownloadDBModel{}
 
 	//需要重置参数
 	tempPath := "/oasis/download/" + task.UUID
@@ -391,7 +262,7 @@ func (p *personService) ReceiveFileData(m model.MessageModel) {
 			if h := file.GetHashByPath(filePath); h == task.Hash {
 				//最终文件比对成功
 				task.State = types.DOWNLOADFINISH
-				p.EditDownloadState(task)
+				//p.EditDownloadState(task)
 				//remove temp path
 				file.RMDir(tempPath)
 			}
@@ -417,7 +288,6 @@ func (p *personService) ReplyGetFileDetail(m model.MessageModel) {
 	summary.Name = f.Name()
 	summary.Size = f.Size()
 	summary.Hash = file.GetHashByPath(path)
-	summary.Path = path
 	summary.BlockSize, summary.Length = file.GetBlockInfo(f.Size())
 
 	msg := model.MessageModel{}
@@ -477,24 +347,24 @@ func (p *personService) SendFileData(m model.MessageModel, blockSize int, length
 // 文件摘要返回
 func (p *personService) ReceiveGetFileDetail(m model.MessageModel) {
 
-	task := p.GetDownloadById("")
-	bss, _ := json.Marshal(m.Data)
-	summary := model.FileSummaryModel{}
-	err := json.Unmarshal(bss, &summary)
-	if err != nil {
-		fmt.Println(err)
-	}
-	task.Hash = summary.Hash
-	task.Length = summary.Length
-	task.Size = summary.Size
+	//	task := p.GetDownloadById("")
+	// bss, _ := json.Marshal(m.Data)
+	// summary := model.FileSummaryModel{}
+	// err := json.Unmarshal(bss, &summary)
+	// if err != nil {
+	// 	fmt.Println(err)
+	// }
+	// task.Hash = summary.Hash
+	// task.Length = summary.Length
+	// task.Size = summary.Size
 
-	p.SaveDownloadState(task)
+	//	p.SaveDownloadState(task)
 }
 
 func AsyncUDPConnect(dst *net.UDPAddr) {
 	for {
 		time.Sleep(2 * time.Second)
-		if _, err := UDPconn.WriteToUDP([]byte(dst.IP.String()+" is ok"), dst); err != nil {
+		if _, err := UDPConn.WriteToUDP([]byte(dst.IP.String()+" is ok"), dst); err != nil {
 			log.Println("send msg fail", err)
 			return
 		} else {
@@ -518,9 +388,13 @@ func UDPService() {
 		KeepAlive:          true,
 	}
 	srcAddr := &net.UDPAddr{
-		IP: net.IPv4zero, Port: 9902} //注意端口必须固定
-	fmt.Println(srcAddr.String())
-	listener, err := quic.ListenAddr(srcAddr.String(), generateTLSConfig(), quicConfig)
+		IP: net.IPv4zero, Port: 9904} //注意端口必须固定
+	var err error
+	UDPConn, err = net.ListenUDP("udp", srcAddr)
+	if err != nil {
+		fmt.Println(err)
+	}
+	listener, err := quic.Listen(UDPConn, generateTLSConfig(), quicConfig)
 	if err != nil {
 		fmt.Println(err)
 	}
@@ -531,6 +405,7 @@ func UDPService() {
 	if err != nil {
 		panic(err)
 	}
+
 	for {
 		select {
 		case <-ctx.Done():
@@ -590,10 +465,8 @@ func UDPService() {
 
 //处理内容
 func ProcessingContent(stream quic.Stream) {
-	//需要处理关闭问题
-
 	for {
-		prefixByte := make([]byte, 4)
+		prefixByte := make([]byte, 6)
 		c1, err := io.ReadFull(stream, prefixByte)
 		fmt.Println(c1)
 		if err != nil {
@@ -619,13 +492,22 @@ func ProcessingContent(stream quic.Stream) {
 			//什么也不做
 			continue
 		} else if m.Type == "directory" {
-			list := MyService.ZiMa().GetDirPath(m.Data.(string))
+			var list []model.Path
+			if m.Data.(string) == "" || m.Data.(string) == "/" {
+				for _, v := range config.FileSettingInfo.ShareDir {
+					tempList := MyService.ZiMa().GetDirPath(v)
+					list = append(list, tempList...)
+				}
+			} else {
+				list = MyService.ZiMa().GetDirPath(m.Data.(string))
+			}
 			m.To = m.From
 			m.Data = list
 			m.From = config.ServerInfo.Token
 			SendData(stream, m)
 			break
 		} else if m.Type == "file_data" {
+
 			SendFileData(stream, m.Data.(string), m.From, m.UUId)
 			break
 		} else if m.Type == types.PERSONADDFRIEND {
@@ -636,7 +518,7 @@ func ProcessingContent(stream quic.Stream) {
 				fmt.Println(err)
 				continue
 			}
-			go MyService.Friend().UpdateAddFriendType(friend)
+			go MyService.Friend().UpdateOrCreate(friend)
 			mi := model2.FriendModel{}
 			mi.Avatar = config.UserInfo.Avatar
 			mi.Profile = config.UserInfo.Description
@@ -647,6 +529,23 @@ func ProcessingContent(stream quic.Stream) {
 			m.From = config.ServerInfo.Token
 
 			SendData(stream, m)
+			break
+		} else if m.Type == "connection" {
+			UDPAddressMap[m.From] = m.Data.(string)
+			fmt.Println("persion", m)
+			mi := model2.FriendModel{}
+			mi.Avatar = config.UserInfo.Avatar
+			mi.Profile = config.UserInfo.Description
+			mi.Name = config.UserInfo.UserName
+			mi.Token = config.ServerInfo.Token
+			msg := model.MessageModel{}
+			msg.Type = types.PERSONADDFRIEND
+			msg.Data = mi
+			msg.To = m.From
+			msg.From = config.ServerInfo.Token
+			msg.UUId = m.UUId
+			Dial(m.Data.(string), msg)
+
 			break
 		} else {
 			//不应有不做返回的数据
@@ -673,20 +572,43 @@ func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
 		fmt.Println("读取失败", err)
 		return err
 	}
+
+	//先发送文件摘要
+
+	summary := model.FileSummaryModel{}
+	summary.BlockSize = blockSize
+	summary.Hash = file.GetHashByPath(filePath)
+	summary.Length = length
+	summary.Name = fStat.Name()
+	summary.Size = fStat.Size()
+
+	msg := model.MessageModel{}
+	msg.Type = "summary"
+	msg.Data = summary
+	msg.From = config.ServerInfo.Token
+	msg.To = to
+	msg.UUId = uuid
+
+	summaryByte, _ := json.Marshal(msg)
+	summaryPrefixLength := file.PrefixLength(len(summaryByte))
+	summaryData := append(summaryPrefixLength, summaryByte...)
+	stream.Write(summaryData)
+
 	bufferedReader := bufio.NewReader(f)
 	buf := make([]byte, blockSize)
 	for i := 0; i < length; i++ {
 
 		tran := model.TranFileModel{}
 
-		_, err = bufferedReader.Read(buf)
+		n, err := bufferedReader.Read(buf)
 
 		if err == io.EOF {
 			fmt.Println("读取完毕", err)
 		}
 
-		tran.Hash = file.GetHashByContent(buf)
+		tran.Hash = file.GetHashByContent(buf[:n])
 		tran.Index = i
+		tran.Length = length
 
 		msg := model.MessageModel{}
 		msg.Type = "file_data"
@@ -695,7 +617,10 @@ func SendFileData(stream quic.Stream, filePath, to, uuid string) error {
 		msg.To = to
 		msg.UUId = uuid
 		b, _ := json.Marshal(msg)
-		stream.Write(b)
+		prefixLength := file.PrefixLength(len(b))
+		dataLength := file.DataLength(len(buf[:n]))
+		data := append(append(append(prefixLength, b...), dataLength...), buf[:n]...)
+		stream.Write(data)
 	}
 	defer stream.Close()
 	return nil

+ 6 - 0
service/service.go

@@ -34,6 +34,7 @@ type Repository interface {
 	Search() SearchService
 	Person() PersonService
 	Friend() FriendService
+	Download() DownloadService
 }
 
 func NewService(db *gorm.DB, log loger2.OLog) Repository {
@@ -57,6 +58,7 @@ func NewService(db *gorm.DB, log loger2.OLog) Repository {
 		search:         NewSearchService(),
 		person:         NewPersonService(db),
 		friend:         NewFriendService(db),
+		download:       NewDownloadService(db),
 	}
 }
 
@@ -79,8 +81,12 @@ type store struct {
 	search         SearchService
 	person         PersonService
 	friend         FriendService
+	download       DownloadService
 }
 
+func (c *store) Download() DownloadService {
+	return c.download
+}
 func (c *store) Friend() FriendService {
 	return c.friend
 }

+ 3 - 4
service/socket.go

@@ -5,7 +5,6 @@ import (
 	"fmt"
 	"net/url"
 	"reflect"
-	"strings"
 	"time"
 
 	"github.com/IceWhaleTech/CasaOS/model"
@@ -53,7 +52,7 @@ func SocketConnect() {
 				m.To = msa.From
 				m.Type = types.PERSONADDFRIEND
 				m.UUId = uuid
-				result, err := Dial("192.168.2.225:9902", m)
+				result, err := Dial("192.168.2.224:9902", m)
 				friend := model2.FriendModel{}
 				if err != nil && !reflect.DeepEqual(result, friend) {
 					dataModelByte, _ := json.Marshal(result.Data)
@@ -91,14 +90,14 @@ func SocketConnect() {
 }
 
 func Connect() {
-	host := strings.Split(config.ServerInfo.Handshake, "://")
-	u := url.URL{Scheme: "ws", Host: host[1], Path: "/v1/ws"}
+	u := url.URL{Scheme: "ws", Host: config.ServerInfo.Handshake + ":8088", Path: "/v1/ws"}
 	for {
 		d, _, e := websocket.DefaultDialer.Dial(u.String(), nil)
 		if e == nil {
 			WebSocketConn = d
 			return
 		}
+		fmt.Println(e)
 		time.Sleep(time.Second * 5)
 	}
 }

+ 91 - 9
service/udpconn.go

@@ -10,19 +10,23 @@ import (
 	"io"
 	"io/ioutil"
 	"net"
+	"os"
 	"strconv"
 	"time"
 
 	"github.com/IceWhaleTech/CasaOS/model"
 	"github.com/IceWhaleTech/CasaOS/pkg/config"
 	"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
+	model2 "github.com/IceWhaleTech/CasaOS/service/model"
+	"github.com/IceWhaleTech/CasaOS/types"
 	"github.com/lucas-clemente/quic-go"
 	uuid "github.com/satori/go.uuid"
 )
 
-var UDPconn *net.UDPConn
+var UDPConn *net.UDPConn
 var PeopleMap map[string]quic.Stream
 var Message chan model.MessageModel
+var UDPAddressMap map[string]string
 
 func Dial(addr string, msg model.MessageModel) (m model.MessageModel, err error) {
 	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@@ -37,8 +41,18 @@ func Dial(addr string, msg model.MessageModel) (m model.MessageModel, err error)
 		NextProtos:             []string{"bench"},
 		SessionTicketsDisabled: true,
 	}
+	srcAddr := &net.UDPAddr{
+		IP: net.IPv4zero, Port: 9904} //注意端口必须固定
+	//addr
+	if len(addr) == 0 {
+		addr = config.ServerInfo.Handshake + ":9527"
+	}
+	dstAddr, err := net.ResolveUDPAddr("udp", addr)
+
+	//DialTCP在网络协议net上连接本地地址laddr和远端地址raddr。net必须是"udp"、"udp4"、"udp6";如果laddr不是nil,将使用它作为本地地址,否则自动选择一个本地地址。
+	//(conn)UDPConn代表一个UDP网络连接,实现了Conn和PacketConn接口
 
-	session, err := quic.DialAddrContext(ctx, addr, tlsConf, quicConfig)
+	session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), tlsConf, quicConfig)
 	if err != nil {
 		return m, err
 	}
@@ -79,11 +93,12 @@ func SendData(stream quic.Stream, m model.MessageModel) {
 	stream.Write(data)
 }
 
+var Summary map[string]model.FileSummaryModel
+
 //读取数据
 func ReadContent(stream quic.Stream) {
-	path := ""
 	for {
-		prefixByte := make([]byte, 4)
+		prefixByte := make([]byte, 6)
 		c1, err := io.ReadFull(stream, prefixByte)
 		fmt.Println(c1, err, string(prefixByte))
 		prefixLength, err := strconv.Atoi(string(prefixByte))
@@ -96,7 +111,7 @@ func ReadContent(stream quic.Stream) {
 		if err != nil {
 			fmt.Println(err)
 		}
-
+		fmt.Println(m)
 		//传输数据需要继续读取
 		if m.Type == "file_data" {
 			dataModelByte, _ := json.Marshal(m.Data)
@@ -121,13 +136,80 @@ func ReadContent(stream quic.Stream) {
 				fmt.Println("hash不匹配", hash, dataModel.Hash)
 			}
 
-			filepath := path + strconv.Itoa(dataModel.Index)
+			tempPath := config.AppInfo.RootPath + "/temp" + "/" + m.UUId
+			file.IsNotExistMkDir(tempPath)
+			filepath := tempPath + "/" + strconv.Itoa(dataModel.Index)
+			tempFile, err := os.Stat(filepath)
+
+			if os.IsNotExist(err) || tempFile.Size() == 0 {
+				err = ioutil.WriteFile(filepath, dataByte, 0644)
+			} else {
+				if file.GetHashByPath(filepath) != dataModel.Hash {
+					os.Remove(filepath)
+					err = ioutil.WriteFile(filepath, dataByte, 0644)
+				}
+			}
+
+			files, err := ioutil.ReadDir(tempPath)
+
+			if len(files) >= dataModel.Length {
+				summary := Summary[m.UUId]
+				file.SpliceFiles(tempPath, config.FileSettingInfo.DownloadDir+"/"+summary.Name, dataModel.Length, 0)
+				if file.GetHashByPath(config.FileSettingInfo.DownloadDir+"/"+summary.Name) == summary.Hash {
+					file.RMDir(tempPath)
+					task := model2.PersionDownloadDBModel{}
+					task.UUID = m.UUId
+					task.State = types.DOWNLOADFINISH
+					MyService.Download().EditDownloadState(task)
+				} else {
+					os.Remove(config.FileSettingInfo.DownloadDir + "/" + summary.Name)
+					task := model2.PersionDownloadDBModel{}
+					task.UUID = m.UUId
+					task.State = types.DOWNLOADERROR
+					MyService.Download().EditDownloadState(task)
+				}
 
-			err = ioutil.WriteFile(filepath, dataByte, 0644)
-			if dataModel.Index >= (dataModel.Length - 1) {
-				//file.SpliceFiles("", path, dataModel.Length)
 				break
 			}
+		} else if m.Type == "summary" {
+
+			dataModel := model.FileSummaryModel{}
+			if m.UUId == m.UUId {
+				dataModelByte, _ := json.Marshal(m.Data)
+				err := json.Unmarshal(dataModelByte, &dataModel)
+				fmt.Println(err)
+			}
+
+			task := model2.PersionDownloadDBModel{}
+			task.UUID = m.UUId
+			task.Name = dataModel.Name
+			task.Length = dataModel.Length
+			task.Size = dataModel.Size
+			task.State = types.DOWNLOADING
+			task.BlockSize = dataModel.BlockSize
+			task.Hash = dataModel.Hash
+			task.Type = 0
+			MyService.Download().SaveDownload(task)
+
+			Summary[m.UUId] = dataModel
+
+		} else if m.Type == "connection" {
+			UDPAddressMap[m.From] = m.Data.(string)
+			fmt.Println("udpconn", m)
+			mi := model2.FriendModel{}
+			mi.Avatar = config.UserInfo.Avatar
+			mi.Profile = config.UserInfo.Description
+			mi.Name = config.UserInfo.UserName
+			mi.Token = config.ServerInfo.Token
+			msg := model.MessageModel{}
+			msg.Type = types.PERSONADDFRIEND
+			msg.Data = mi
+			msg.To = m.From
+			msg.From = config.ServerInfo.Token
+			msg.UUId = m.UUId
+			Dial(m.Data.(string), msg)
+			Message <- m
+			break
 		} else {
 			Message <- m
 		}