-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprotocol.lua
121 lines (91 loc) · 2.64 KB
/
protocol.lua
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
-- protocol.lua
-- (C) 2009, Michael Meier
local rpcidlength = 8
-- packet table -> binary string
function encodepacket(info, headervers)
local chunks = {}
local hv
if headervers == nil then
hv = 1
else
if headervers == 1 then
hv = 1
else
error("unsupported header version")
end
end
table.insert(chunks, string.char(hv))
if hv == 1 then
local rpcid = info.rpcid
local fromid = info.fromid
local call = info.call
if #rpcid ~= rpcidlength then error("rpcid has to be 8 bytes long") end
if #fromid ~= 20 then error("fromid has to be 20 bytes long") end
if call > 255 or call < 0 then error("call has to be a character number") end
table.insert(chunks, fromid)
table.insert(chunks, rpcid)
table.insert(chunks, string.char(call))
if info.payload and (call == 1 or call==129) then
local encoded = bencode(info.payload)
local len = #encoded
if len > 0xffff then error("payload too long") end
-- generate single bytes for encoding in network byte order
local msb = math.floor(len / 256)
local lsb = len - (msb * 256)
table.insert(chunks, string.char(msb))
table.insert(chunks, string.char(lsb))
table.insert(chunks, encoded)
end
else
end
return table.concat(chunks)
end
-- raw packet table -> packet table
function decodepacket(packet)
packet.decoded = false
local raw = packet.raw
local hv = string.byte(raw:sub(1, 1))
if hv == 1 then
local fromid = raw:sub(2, 21)
local rpcid = raw:sub(22, 29)
local call = raw:sub(30, 30)
--print("decoding header type 1")
--print("fromid " .. fromid)
--print("rpcid " .. rpcid)
--print("call " .. call)
if call == "" then return end
call = string.byte(call)
packet.from.id = fromid
packet.from.unique = packet.from.addr .. "|" .. packet.from.port .. "|" .. fromid
packet.rpcid = rpcid
packet.call = call
-- error packets don't have payload
if call == 130 or call == 131 then
packet.decoded = true
return
end
if packet.call == 1 or packet.call == 129 then
local msb = string.byte(raw:sub(31, 31))
if msb == nil then
packet.payload = {}
packet.decoded = true
return
end
local lsb = string.byte(raw:sub(32, 32))
if lsb == nil then return end
local len = (msb * 256) + lsb
local encoded = raw:sub(33, 33 + len - 1)
if #encoded ~= len then return end
local ok, payload = pcall(debencode, encoded)
if ok then
packet.payload = payload
packet.decoded = true
else
return
end
end
return
else
return
end
end