-
Notifications
You must be signed in to change notification settings - Fork 1
/
iac.js
129 lines (106 loc) · 3.78 KB
/
iac.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
const charcodesOf = str => [...str]
.map(char => char.charCodeAt(0))
const EventEmitter = require('events')
let operations = module.exports = new Proxy({
will: 251, // Sender WILL do something
wont: 252, // Sender WONT do something
do: 253, // Sender is saying DO something
dont: 254, // Sender is saying DONT do something
sb: 250, // Subnegotiation
on: ()=>{},
}, {
get(target, key) {
if (key === 'valueOf') return operations
const op = key = key.toString().toLowerCase()
const iac = 255
const se = 240
const operation = target[key]
if (typeof operation === 'undefined') return undefined
if (key === 'on') {
return (sock, command, handler) => {
if (!(sock instanceof EventEmitter))
throw new TypeError('sock must be EventEmitter')
if (typeof command === 'undefined')
throw new TypeError('command must be defined')
if (!(handler instanceof Function))
throw new TypeError('handler must be Function')
const [ expectedIac, expectedOperation, expectedOption ] = command instanceof Buffer
? command.toJSON().data
: command instanceof Function
? command().toJSON().data.slice(0, 3)
: command.toArray
sock.on('data', data => {
const [ remoteIac, remoteOperation, remoteOption, ...args ] = data.toJSON().data
if (expectedIac === remoteIac
&& (!expectedOperation || expectedOperation === remoteOperation)
&& (!expectedOption || expectedOption === remoteOption)) {
if (expectedOption) {
if (remoteOperation === 250) {
// Subnegotiation
let subargs = []
let currSubarg = []
args.pop() // SE
for (let i in args) {
let arg = args[i]
if (arg === 0 || arg === 255) {
if (currSubarg.length)
subargs.push(currSubarg)
currSubarg = []
} else {
currSubarg.push(arg)
}
}
handler(...subargs)
} else {
handler(...args)
}
} else {
handler(remoteOption, ...args)
}
}
})
return operations
}
}
let options = new Proxy({
binary: 0, // Binary Transmission
echo: 1, // Echo
suppress: 3, // Suppress Go Ahead
status: 5, // Status
timing: 6, // Timing Mark
terminal: 24, // Terminal Type
naws: 31, // Negotiate About Window Size
speed: 32, // Terminal Speed
flow: 33, // Remote Flow Control
linemode: 34, // Linemode
env: 36, // Environment Variables
}, {
get(target, key) {
if (key === 'valueOf') return `IAC ${op}`
if (key === 'toArray') return [ 255, operation ]
key = key.toString().toLowerCase()
const option = target[key]
if (typeof option === 'undefined') return undefined
if (operation === 250) {
// Subnegotiation
return (...args) => {
let res = [ iac, operation, option ]
if (args.length === 0) {
// Value Requested
res.push(1)
} else {
for (let arg of args) {
// Value Given
if (arg instanceof Number) res.push(0, arg)
else res.push(0, ...charcodesOf(arg))
}
}
res.push(iac, se)
return new Buffer(res)
}
} else return new Buffer([ iac, operation, option ])
}
})
return options
}
})