|
1 var protocol = exports; |
|
2 |
|
3 // |
|
4 // ### function parseSynHead (type, flags, data) |
|
5 // #### @type {Number} Frame type |
|
6 // #### @flags {Number} Frame flags |
|
7 // #### @data {Buffer} input data |
|
8 // Returns parsed syn_* frame's head |
|
9 // |
|
10 protocol.parseSynHead = function parseSynHead(type, flags, data) { |
|
11 var stream = type === 0x01; |
|
12 |
|
13 return { |
|
14 type: stream ? 'SYN_STREAM' : 'SYN_REPLY', |
|
15 id: data.readUInt32BE(0, true) & 0x7fffffff, |
|
16 version: 3, |
|
17 associated: stream ? data.readUInt32BE(4, true) & 0x7fffffff : 0, |
|
18 priority: stream ? data[8] >> 5 : 0, |
|
19 fin: (flags & 0x01) === 0x01, |
|
20 unidir: (flags & 0x02) === 0x02, |
|
21 _offset: stream ? 10 : 4 |
|
22 }; |
|
23 }; |
|
24 |
|
25 // |
|
26 // ### function parseHeaders (pairs) |
|
27 // #### @pairs {Buffer} header pairs |
|
28 // Returns hashmap of parsed headers |
|
29 // |
|
30 protocol.parseHeaders = function parseHeaders(pairs) { |
|
31 var count = pairs.readUInt32BE(0, true), |
|
32 headers = {}; |
|
33 |
|
34 pairs = pairs.slice(4); |
|
35 |
|
36 function readString() { |
|
37 var len = pairs.readUInt32BE(0, true), |
|
38 value = pairs.slice(4, 4 + len); |
|
39 |
|
40 pairs = pairs.slice(4 + len); |
|
41 |
|
42 return value.toString(); |
|
43 } |
|
44 |
|
45 while(count > 0) { |
|
46 headers[readString().replace(/^:/, '')] = readString(); |
|
47 count--; |
|
48 } |
|
49 |
|
50 return headers; |
|
51 }; |
|
52 |
|
53 // |
|
54 // ### function parsesRst frame |
|
55 protocol.parseRst = function parseRst(data) { |
|
56 return { |
|
57 type: 'RST_STREAM', |
|
58 id: data.readUInt32BE(0, true) & 0x7fffffff, |
|
59 status: data.readUInt32BE(4, true) |
|
60 }; |
|
61 }; |
|
62 |
|
63 protocol.parseSettings = function parseSettings(data) { |
|
64 var settings = {}, |
|
65 number = data.readUInt32BE(0, true), |
|
66 idMap = { |
|
67 1: 'upload_bandwidth', |
|
68 2: 'download_bandwidth', |
|
69 3: 'round_trip_time', |
|
70 4: 'max_concurrent_streams', |
|
71 5: 'current_cwnd', |
|
72 6: 'download_retrans_rate', |
|
73 7: 'initial_window_size', |
|
74 8: 'client_certificate_vector_size' |
|
75 }; |
|
76 |
|
77 for (var i=0; i<number; i++) { |
|
78 var id = data.readUInt32BE(4 + (i*8), true) & 0x00ffffff, |
|
79 flags = data.readUInt8(4 + (i*8), true), |
|
80 name = idMap[id]; |
|
81 settings[id] = settings[name] = { |
|
82 persist: !!(flags & 0x1), |
|
83 persisted: !!(flags & 0x2), |
|
84 value: data.readUInt32BE(8 + (i*8), true) |
|
85 }; |
|
86 } |
|
87 |
|
88 return { |
|
89 type: 'SETTINGS', |
|
90 settings: settings |
|
91 }; |
|
92 }; |
|
93 |
|
94 protocol.parseGoaway = function parseGoaway(data) { |
|
95 return { |
|
96 type: 'GOAWAY', |
|
97 lastId: data.readUInt32BE(0, true) & 0x7fffffff |
|
98 }; |
|
99 }; |
|
100 |
|
101 protocol.parseWindowUpdate = function parseWindowUpdate(data) { |
|
102 var ret = { |
|
103 type: 'WINDOW_UPDATE', |
|
104 id: data.readUInt32BE(0, true) & 0x7fffffff, |
|
105 delta: data.readUInt32BE(4, true) & 0x7fffffff |
|
106 }; |
|
107 |
|
108 return ret; |
|
109 }; |