| 145 | } |
| 146 | |
| 147 | async _parseRequest(): Promise<{ host: string, port: number, command: SocksCommand }> { |
| 148 | // Request. |
| 149 | // +----+-----+-------+------+----------+----------+ |
| 150 | // |VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT | |
| 151 | // +----+-----+-------+------+----------+----------+ |
| 152 | // | 1 | 1 | X'00' | 1 | Variable | 2 | |
| 153 | // +----+-----+-------+------+----------+----------+ |
| 154 | |
| 155 | // Response. |
| 156 | // +----+-----+-------+------+----------+----------+ |
| 157 | // |VER | REP | RSV | ATYP | BND.ADDR | BND.PORT | |
| 158 | // +----+-----+-------+------+----------+----------+ |
| 159 | // | 1 | 1 | X'00' | 1 | Variable | 2 | |
| 160 | // +----+-----+-------+------+----------+----------+ |
| 161 | |
| 162 | const version = await this._readByte(); |
| 163 | assert(version === 0x05, 'The VER field must be set to x05 for this version of the protocol, was ' + version); |
| 164 | |
| 165 | const command = await this._readByte(); |
| 166 | await this._readByte(); // skip reserved. |
| 167 | const addressType = await this._readByte(); |
| 168 | let host = ''; |
| 169 | switch (addressType) { |
| 170 | case SocksAddressType.IPv4: |
| 171 | host = (await this._readBytes(4)).join('.'); |
| 172 | break; |
| 173 | case SocksAddressType.FqName: |
| 174 | const length = await this._readByte(); |
| 175 | host = (await this._readBytes(length)).toString(); |
| 176 | break; |
| 177 | case SocksAddressType.IPv6: |
| 178 | const bytes = await this._readBytes(16); |
| 179 | const tokens: string[] = []; |
| 180 | for (let i = 0; i < 8; ++i) |
| 181 | tokens.push(bytes.readUInt16BE(i * 2).toString(16)); |
| 182 | host = tokens.join(':'); |
| 183 | break; |
| 184 | } |
| 185 | const port = (await this._readBytes(2)).readUInt16BE(0); |
| 186 | |
| 187 | this._buffer = Buffer.from([]); |
| 188 | this._offset = 0; |
| 189 | this._fence = 0; |
| 190 | |
| 191 | return { |
| 192 | command, |
| 193 | host, |
| 194 | port |
| 195 | }; |
| 196 | } |
| 197 | |
| 198 | private async _readByte(): Promise<number> { |
| 199 | const buffer = await this._readBytes(1); |