This repository has been archived by the owner on Nov 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
upload.go
99 lines (92 loc) · 1.99 KB
/
upload.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package sandy
import (
"errors"
"fmt"
"io"
"log"
"net"
"time"
)
// Peanut for sandy
type Peanut struct {
Protein io.ReadCloser
Name string
Size int64
Feedback chan string
}
// Upload feed sandy
func Upload(server string, p *Peanut) error {
defer func() {
close(p.Feedback)
p.Protein.Close()
}()
udpAddr, err := net.ResolveUDPAddr("udp", server)
if err != nil {
log.Println("resolve server address failed", err)
return err
}
conn, err := net.DialUDP("udp", nil, udpAddr)
if err != nil {
log.Println("dialUDP failed", err)
return err
}
defer conn.Close()
hs := encodeHandshake([]byte(p.Name))
n, err := conn.Write(hs)
if err != nil {
log.Println("conn write failed")
return err
}
rBuf := make([]byte, n)
conn.SetReadDeadline(time.Now().Add(2 * readUDPTimeout))
m, _, err := conn.ReadFromUDP(rBuf[:])
if err != nil {
log.Println("readFromUDP failed", err)
return err
}
if m != n || string(rBuf) != string(hs) {
log.Println("do not get 'handshake' back, handshake failed")
return err
}
var accumulated int64
size := p.Size
var fBuf [bufSize]byte
var dummy [1]byte
p.Feedback <- fmt.Sprintf("going to upload: %q\r", p.Name)
t := time.NewTicker(3 * time.Second)
defer t.Stop()
for {
n, err := p.Protein.Read(fBuf[:])
if err != nil {
if errors.Is(err, io.EOF) {
break
}
log.Println("read file err", err)
return err
}
m, err := conn.Write(fBuf[:n])
if err != nil {
log.Println("conn write failed", err)
return err
}
accumulated += int64(m)
select {
case <-t.C:
p.Feedback <- fmt.Sprintf("%s: progress: %v/%v kb (%.2f%%)\r",
p.Name,
accumulated/1024,
size/1024,
100*float64(accumulated)/float64(size))
default:
conn.SetReadDeadline(time.Now().Add(readUDPTimeout))
conn.ReadFrom(dummy[:])
}
}
p.Feedback <- fmt.Sprintf("%s: progress: %v/%v kb (%.2f%%)\r\n",
p.Name,
accumulated/1024,
size/1024,
100*float64(accumulated)/float64(size))
_, err = conn.Write([]byte(hangUPEOF))
return err
}