-
Notifications
You must be signed in to change notification settings - Fork 1
/
p2p.go
106 lines (82 loc) · 1.96 KB
/
p2p.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
100
101
102
103
104
105
106
package main
import (
"crypto/rand"
"fmt"
"log"
"net"
"strings"
"time"
)
var connection *net.UDPConn = nil
var remoteAddress *net.UDPAddr = nil
func tokenGenerator() string {
b := make([]byte, 5)
rand.Read(b)
return fmt.Sprintf("%x", b)
}
func newConnection(remote *net.UDPAddr, local *net.UDPAddr) error {
c, err := net.ListenUDP("udp", local)
if err != nil {
return err
}
log.Println("Listening on: ", c.LocalAddr().String())
fmt.Print("Starting connection")
i := 0
ourToken := tokenGenerator()
currentToken := ourToken
for {
c.SetDeadline(time.Time{})
c.WriteToUDP([]byte(currentToken), remote)
if i%4 == 0 {
fmt.Print(".")
}
c.SetDeadline(time.Now().Add(50 * time.Millisecond))
buf := make([]byte, 1024)
n, _, _ := c.ReadFromUDP(buf)
if n > 0 {
if strings.Contains(string(buf[0:n]), ourToken) {
//They have recieved our communication which means their nat has a hole
log.Println("Punched! ", string(buf[0:n]))
c.SetDeadline(time.Time{})
c.WriteToUDP([]byte(currentToken), remote)
break
}
if len(currentToken) != len(ourToken)*2 {
currentToken = ourToken + string(buf[0:n])
}
log.Println("current [", currentToken, "], recieved [", string(buf[0:n]), "] our [", ourToken, "]")
}
i++
}
go func() {
for {
<-time.After(time.Millisecond * 100)
c.WriteToUDP([]byte("|heartbeat|"), remote)
}
}()
fmt.Print("Connection Established!\n")
connection = c
remoteAddress = remote
return nil
}
func readData(output chan<- string) {
if connection == nil {
panic("Tried to start reading before connection was started")
}
go func() {
for {
buf := make([]byte, 1024)
n, _, err := connection.ReadFromUDP(buf)
if err != nil {
continue
}
output <- string(buf[0:n])
}
}()
}
func writeData(data string) {
if connection == nil || remoteAddress == nil {
panic("Tried to call write before connection was established")
}
connection.WriteToUDP([]byte(data), remoteAddress)
}