-
Notifications
You must be signed in to change notification settings - Fork 2
/
directip-testserver.go
124 lines (113 loc) · 2.9 KB
/
directip-testserver.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package sbd
import (
"encoding/binary"
"log"
"net"
)
type DIPHandler func(mg *MessageHeader, dih *DirectIPHeader, payload []byte, priority *int) Confirmation
func handle(mg *MessageHeader, dih *DirectIPHeader, payload []byte, priority *int) Confirmation {
log.Printf("MH: %v, DIH: %v, Data: %v, Prio: %v", mg, dih, payload, priority)
return Confirmation{}
}
func onError(e error) {
log.Printf("Error: %v", e)
}
// A DIPServer is a server which can listen on an given tcp address
// and parses the incoming directip messages. Set the Handler-Field
// to implement your wanted behaviour. The default is simply logging.
type DIPServer struct {
address string
listener net.Listener
confirmation confirmationMessage
Handle DIPHandler
OnError func(error)
}
func (ts *DIPServer) start() {
go func() {
for {
con, err := ts.listener.Accept()
if err != nil {
return
}
go func(con net.Conn) {
defer con.Close()
var res MessageHeader
if err := binary.Read(con, binary.BigEndian, &res); err != nil {
ts.OnError(err)
return
}
var dih mtDirectIPHeader
if err := binary.Read(con, binary.BigEndian, &dih); err != nil {
ts.OnError(err)
return
}
read := binary.Size(dih)
var data []byte
var prio *int
for read < int(res.MessageLength) {
var ph Header
if err := binary.Read(con, binary.BigEndian, &ph); err != nil {
ts.OnError(err)
return
}
if ph.ID == mtPayloadID {
data = make([]byte, ph.ElementLength)
if _, err := con.Read(data); err != nil {
ts.OnError(err)
return
}
read += int(ph.ElementLength) + binary.Size(ph)
}
if ph.ID == mtMessagePriority {
var mtp mtPriority
if err := binary.Read(con, binary.BigEndian, &mtp); err != nil {
ts.OnError(err)
return
}
read += binary.Size(mtp)
i := int(mtp.Level)
prio = &i
}
}
conf := ts.Handle(&res, &dih.DirectIPHeader, data, prio)
confgMsg := confirmationMessage{
MessageHeader: MessageHeader{
ProtocolRevision: protocolRevision,
MessageLength: 25,
},
Header: Header{
ID: mtConfirmationMsg,
ElementLength: 25,
},
Confirmation: conf,
}
binary.Write(con, binary.BigEndian, &confgMsg)
}(con)
}
}()
}
// Close closes the server so it does not accept any more connections.
func (ts *DIPServer) Close() {
ts.listener.Close()
}
// Start starts listening. This function will block!
func (ts *DIPServer) Start() {
ts.start()
}
func (ts *DIPServer) reset() {
ts.Handle = handle
ts.OnError = onError
}
// NewDIPServer returns a new directip server listening on the given address.
func NewDIPServer(address string) (*DIPServer, error) {
ls, err := net.Listen("tcp", address)
if err != nil {
return nil, err
}
ts := DIPServer{
address: ls.Addr().String(),
listener: ls,
}
ts.reset()
return &ts, nil
}