-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmessageParseUDP.js
153 lines (146 loc) · 3.83 KB
/
messageParseUDP.js
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
* UDP Message Parser
*
* Parses incoming UDP messages based on expected BitTorrent UDP spec
* message formats
*
* Packages numerical arrays into Buffer for transmission via UDP
* packet.
*
*/
var DEFAULT = require("./default.js");
var fs = require("fs");
var parse = function parse(buffer){
var action;
var index;
var output;
var lengthError;
index = 0;
output = {};
lengthError = "Packet length too short, likely missing data";
if(buffer.length >= 4){
action = buffer.readUInt32BE(index);
if(action > 3){
action = buffer.readUInt32LE(index);
}
index += 4;
output.action = action;
switch(action){
case 0:
if(buffer.length >= 16){
output.transaction_id = buffer.readUInt32BE(index);
index += 4;
output.connection_id = buffer.readDoubleBE(index);
}
else{
output.error = lengthError;
}
break;
case 1:
if(buffer.length >= 20){
var ip;
var port;
output.transaction_id = buffer.readUInt32BE(index);
index += 4;
output.interval = buffer.readUInt32BE(index);
index += 4;
output.leechers = buffer.readUInt32BE(index);
index += 4;
output.seeders = buffer.readUInt32BE(index);
index += 4;
output.peers = [];
while(buffer.length - index >= 6){
ip = buffer.readUInt8(index) + "." + buffer.readUInt8(index + 1) + "." + buffer.readUInt8(index + 2) + "." + buffer.readUInt8(index + 3);
port = buffer.readUInt16BE(index + 4);
output.peers.push({ip: ip, port:port});
index += 6;
}
}
else{
output.error = lengthError;
}
break;
case 2:
output.error = "Scrape requests not supported";
// TODO - low priority
break;
case 3:
if(buffer.length >= 8){
output.transaction_id = buffer.readUInt32BE(index);
index += 4;
output.error = buffer.toString("utf8", 8, buffer.length);
}
else{
output.error = lengthError;
}
break;
default:
output.error = "Action value " + action + " not supported or recognized";
}
}
else{
output.error = lengthError;
}
return output;
};
var pkg = function pkg(msg){
var output;
var index = 0;
switch(msg.type){
case "connect":
output = new Buffer(16);
output.writeUInt32BE(DEFAULT.UDP_DEFAULT1, index);
index += 4;
output.writeUInt32BE(DEFAULT.UDP_DEFAULT2, index);
index += 4;
output.writeUInt32BE(0, index);
index += 4;
output.writeUInt32BE(msg.transaction_id, index);
break;
case "announce":
output = new Buffer(98);
output.writeDoubleBE(msg.connection_id, index);
index += 8;
output.writeUInt32BE(1, index);
index += 4;
output.writeUInt32BE(msg.transaction_id, index);
index += 4;
output.write(msg.info_hash, index, 20, "hex");
index += 20;
output.write(msg.peerid, index, 20, "utf-8");
index += 20;
output.writeUInt32BE(msg.downloaded / 0xffffffff, index);
index += 4;
output.writeUInt32BE(msg.downloaded % 0xffffffff, index);
index += 4;
output.writeUInt32BE(msg.left / 0xffffffff, index);
index += 4;
output.writeUInt32BE(msg.left % 0xffffffff, index);
index += 4;
output.writeUInt32BE(msg.uploaded / 0xffffffff, index);
index += 4;
output.writeUInt32BE(msg.uploaded % 0xffffffff, index);
index += 4;
output.writeUInt32BE(types[msg.event], index);
index += 4;
output.writeUInt32BE(msg.ip || 0, index);
index += 4;
output.writeUInt32BE(msg.key, index);
index += 4;
output.writeUInt32BE(msg.num_want || -1, index);
index += 4;
output.writeUInt16BE(msg.port || DEFAULT.DEFAULT_PORT, index);
break;
case "default":
output.error = "Message type unsupported";
}
return output;
};
var types = ["none", "completed", "started", "stopped"];
types["none"] = 0;
types["completed"] = 1;
types["started"] = 2;
types["stopped"] = 3;
module.exports.parse = parse;
module.exports.pkg = pkg;
module.exports.types = types;