-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprotocol.go
104 lines (96 loc) · 2.34 KB
/
protocol.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
package main
import (
"crypto/sha256"
"encoding/binary"
"sync"
"time"
"github.com/golang/protobuf/proto"
"github.com/howardstark/fusion/protos"
log "github.com/sirupsen/logrus"
)
var (
packetDedupLock sync.Mutex
packetDedup = make(map[[32]byte]bool)
)
func shouldDedup(packet packets.Packet) bool {
switch packet.GetBody().(type) {
case *packets.Packet_Data:
return false
case *packets.Packet_Status:
return true
case *packets.Packet_Control:
return true
}
panic("what is this packet")
}
func dedup(packet packets.Packet, rawPacket []byte) bool {
if !shouldDedup(packet) {
return false
}
hash := sha256.Sum256(rawPacket)
packetDedupLock.Lock()
defer packetDedupLock.Unlock()
_, ok := packetDedup[hash]
if ok {
//fmt.Println("Ignoring already received packet with hash", hash)
return true
}
packetDedup[hash] = true
return false
}
func (sess *Session) wrap(data []byte) *OutgoingPacket {
seq := sess.incrementOutgoingSeq()
//fmt.Println("Wrapping packet with seq", seq)
packet := packets.Packet{
Body: &packets.Packet_Data{
Data: &packets.Data{
SequenceID: seq,
Content: data,
},
},
}
//log.Debug("Packet constructed")
marshalled := marshal(&packet)
sess.outgoingLock.Lock()
defer sess.outgoingLock.Unlock()
out := &OutgoingPacket{
seq: seq,
data: &marshalled,
session: sess,
date: time.Now().UnixNano(),
}
sess.outgoing[seq] = out
return out
}
func marshal(packet *packets.Packet) []byte {
packetData, packetErr := proto.Marshal(packet)
if packetErr != nil {
log.WithError(packetErr).Panic("Marshal error")
return nil
}
if len(packetData) >= 65535 {
log.Error("Packet too large")
return nil
}
packetLen := make([]byte, 2)
binary.BigEndian.PutUint16(packetLen, uint16(len(packetData)))
packetData = append(packetLen, packetData...)
return packetData
}
func readProtoPacket(conn *Connection) (packets.Packet, error, []byte) {
var packet packets.Packet
packetLen := make([]byte, 2)
lenErr := conn.ReadFull(packetLen)
if lenErr != nil {
return packet, lenErr, nil
}
l := binary.BigEndian.Uint16(packetLen)
log.Debug("Reading packet of length ", l)
packetData := make([]byte, l)
dataErr := conn.ReadFull(packetData)
if dataErr != nil {
return packet, dataErr, packetData
}
unmarshErr := proto.Unmarshal(packetData, &packet)
return packet, unmarshErr, packetData
}