diff --git a/src/communicator.ts b/src/communicator.ts index 5e3e008..d13b65f 100644 --- a/src/communicator.ts +++ b/src/communicator.ts @@ -6,6 +6,7 @@ import BaseService from "./services/base"; export interface User { uin: string, + username: string, password: string, memberSince: Date, } @@ -97,8 +98,16 @@ export default class Communicator { } const tlv = TLV.fromBuffer(message.payload.slice(4)); + console.log('thing sent to channel 1:'); console.log(tlv.toString()); + if (tlv.type === 0x06) { + // client sent us a cookie + const {cookie, user} = JSON.parse(tlv.payload.toString()); + console.log('cookie:', cookie); + this.user = user; + } + if (tlv.type === TLVType.GetServices) { // Requesting available services // this is just a dword list of subtype families const servicesOffered : Buffer[] = []; diff --git a/src/main-chat.ts b/src/main-chat.ts index 530b2a0..3db9c37 100644 --- a/src/main-chat.ts +++ b/src/main-chat.ts @@ -47,9 +47,9 @@ const server = net.createServer((socket) => { new PrivacyManagement(comm), new UserLookup(comm), new UsageStats(comm), - new ChatNavigation(comm), - new Chat(comm), - new DirectorySearch(comm), + // new ChatNavigation(comm), + // new Chat(comm), + // new DirectorySearch(comm), new ServerStoredBuddyIcons(comm), new SSI(comm), ]; diff --git a/src/services/0x01-GenericServiceControls.ts b/src/services/0x01-GenericServiceControls.ts index faf5514..ac83e46 100644 --- a/src/services/0x01-GenericServiceControls.ts +++ b/src/services/0x01-GenericServiceControls.ts @@ -31,11 +31,21 @@ export default class GenericServiceControls extends BaseService { } if (message.payload.subtype === 0x06) { // Client ask server for rate limits info + + // HACK: set rate limits for all services. I can't tell which message subtypes they support so + // make it set rate limits for everything under 0x21. + const pairs : RateGroupPair[] = []; + Object.values(this.communicator.services).forEach((service) => { + for (let i = 0; i < 0x21; i++) { + pairs.push(new RateGroupPair(service.service, i)); + } + }); + const resp = new FLAP(0x02, this.nextReqID, SNAC.forRateClass(0x01, 0x07, [ new Rate( new RateClass(1, 80, 2500, 2000, 1500, 800, 3400 /*fake*/, 6000, 0, 0), - new RatedServiceGroup(1, [new RateGroupPair(0x00, 0x00)]) + new RatedServiceGroup(1, pairs), ) ])) this.send(resp); @@ -50,7 +60,7 @@ export default class GenericServiceControls extends BaseService { } if (message.payload.subtype === 0x0e) { // Client requests own online information - const uin = '400'; // this.communicator.user.uin; + const uin = this.communicator.user?.username || 'user'; const warning = 0; const since = +(new Date('December 17, 1998 03:24:00')); const externalIP = dot2num(this.communicator.socket.remoteAddress!.split(':').pop()!); diff --git a/src/services/0x04-ICBM.ts b/src/services/0x04-ICBM.ts index 2bf0106..329846f 100644 --- a/src/services/0x04-ICBM.ts +++ b/src/services/0x04-ICBM.ts @@ -57,7 +57,6 @@ export default class ICBM extends BaseService { const channel = payload.readUInt16BE(0); // TODO: set settings based on channel provided - this.channel = { channel, messageFlags: payload.readUInt32BE(2), @@ -65,7 +64,7 @@ export default class ICBM extends BaseService { maxSenderWarningLevel: payload.readUInt16BE(8), maxReceiverWarningLevel: payload.readUInt16BE(10), minimumMessageInterval: payload.readUInt16BE(12), - unknown: payload.readUInt16BE(14), + unknown: 1000, //payload.readUInt16BE(14), } console.log("ICBM set channel", this.channel); return; @@ -81,10 +80,6 @@ export default class ICBM extends BaseService { payload.writeInt16BE(this.channel.minimumMessageInterval, 12); payload.writeInt16BE(this.channel.unknown, 14); - // For some reason this response crashes the client? - // It's identical to the channel set request the client - // sends earlier. Also the 3.x client sends a channel set request - // so early const resp = new FLAP(0x02, this.nextReqID, new SNAC(0x04, 0x05, payload)); this.send(resp); diff --git a/src/services/0x13-SSI.ts b/src/services/0x13-SSI.ts index f06d620..ca8168c 100644 --- a/src/services/0x13-SSI.ts +++ b/src/services/0x13-SSI.ts @@ -4,6 +4,6 @@ import Communicator from '../communicator'; // SSI is Server Stored Information export default class SSI extends BaseService { constructor(communicator : Communicator) { - super({service: 0x10, version: 0x01}, communicator) + super({service: 0x13, version: 0x01}, communicator) } } diff --git a/src/services/0x17-AuthorizationRegistration.ts b/src/services/0x17-AuthorizationRegistration.ts index 3f0e109..3e439fa 100644 --- a/src/services/0x17-AuthorizationRegistration.ts +++ b/src/services/0x17-AuthorizationRegistration.ts @@ -9,6 +9,7 @@ const { AIM_MD5_STRING, FLAGS_EMPTY } = require('../consts'); const users : {[key: string]: User} = { 'toof': { uin: '156089', + username: 'toof', password: 'foo', memberSince: new Date('December 17, 1998 03:24:00'), } @@ -87,12 +88,18 @@ export default class AuthorizationRegistrationService extends BaseService { new SNAC(0x17, 0x03, [ TLV.forUsername(username), // username TLV.forBOSAddress(chatHost), // BOS address - TLV.forCookie(JSON.stringify({cookie: 'uwu', user: 'toof'})) // Authorization cookie + TLV.forCookie(JSON.stringify({cookie: 'uwu', user: users[username]})) // Authorization cookie ])); - this.communicator.user = Object.assign({}, users[username], {username}); + this.communicator.user = Object.assign({username}, users[username]); + console.log(this.communicator.user); this.send(authResp); + + // tell them to leave + const disconnectResp = new FLAP(4, this.nextReqID, Buffer.alloc(0)); + this.send(disconnectResp); + return; case 0x06: // Request md5 authkey const MD5AuthKeyHeader = Buffer.alloc(2, 0xFF, 'hex'); diff --git a/src/util.ts b/src/util.ts index 314aa83..9416f9f 100644 --- a/src/util.ts +++ b/src/util.ts @@ -29,6 +29,7 @@ interface Spec { isRepeat? : boolean, isParam? : boolean, isTLV? : boolean, + dump? : boolean, repeatSpecs?: Spec[], } @@ -56,6 +57,10 @@ function tlv(description : string) : Spec { return {size : -1, description, isTLV: true}; } +function dump() : Spec { + return {size: -1, description: '', dump: true}; +} + function parseBuffer(buf : Buffer, spec : Spec[], repeatTimes = 0) { let offset = 0; let rows = []; @@ -64,6 +69,12 @@ function parseBuffer(buf : Buffer, spec : Spec[], repeatTimes = 0) { for (let section of spec) { let value : any = 0; let bufStr : string = ''; + + if (section.dump) { + rows.push({raw: logDataStream(buf.slice(offset))}); + break; + } + if (section.size === 8) { bufStr = buf.slice(offset, offset + 1).toString('hex'); value = buf.readInt8(offset); @@ -127,7 +138,15 @@ function parseBuffer(buf : Buffer, spec : Spec[], repeatTimes = 0) { function printBuffer(buf : Buffer, spec : Spec[]) { const rows = parseBuffer(buf, spec); - console.log((new Table(rows)).toString()); + + const lastRow = rows[rows.length - 1]; + + if (!!lastRow.raw) { + console.log((new Table(rows.slice(0, -1))).toString()); + console.log(lastRow.raw); + } else { + console.log((new Table(rows)).toString()); + } } function bufferFromWebText(webtext : string) : Buffer { @@ -169,7 +188,7 @@ const SNAC_01_0F = [ dword("Last EXT status update time"), ]; -const exampleWebText = ''+ +const exSNAC_01_0F = ''+ ` 2a 02 00 05 00 71 00 01 00 0f 00 00 00 00 00 00 @@ -186,8 +205,91 @@ const exampleWebText = ''+ 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 +`; + +const SNAC_01_07 = [ + byte("FLAP Header"), + byte("Channel"), + word("Sequence ID"), + word("Payload Length"), + word("SNAC Family"), + word("SNAC Subtype"), + word("SNAC Flags"), + dword("SNAC Request-ID"), + + repeat(16, "Number of Rate Classes", [ + word('Rate class ID'), + dword('Window size'), + dword('Clear level'), + dword('Alert level'), + dword('Limit level'), + dword('Disconnect level'), + dword('Current level'), + dword('Max level'), + dword('Last time'), + byte('Current State'), + ]), + + dump(), +]; + +const exSNAC_01_07 = ''+ ` +2a 02 00 05 03 3b 00 01 00 07 00 00 00 00 +00 00 00 05 00 01 00 00 00 50 00 00 09 c4 00 00 +07 d0 00 00 05 dc 00 00 03 20 00 00 16 dc 00 00 +17 70 00 00 00 00 00 00 02 00 00 00 50 00 00 0b +b8 00 00 07 d0 00 00 05 dc 00 00 03 e8 00 00 17 +70 00 00 17 70 00 00 00 7b 00 00 03 00 00 00 1e +00 00 0e 74 00 00 0f a0 00 00 05 dc 00 00 03 e8 +00 00 17 70 00 00 17 70 00 00 00 00 00 00 04 00 +00 00 14 00 00 15 7c 00 00 14 b4 00 00 10 68 00 +00 0b b8 00 00 17 70 00 00 1f 40 00 00 00 7b 00 +00 05 00 00 00 0a 00 00 15 7c 00 00 14 b4 00 00 +10 68 00 00 0b b8 00 00 17 70 00 00 1f 40 00 00 +00 7b 00 00 01 00 91 00 01 00 01 00 01 00 02 00 +01 00 03 00 01 00 04 00 01 00 05 00 01 00 06 00 +01 00 07 00 01 00 08 00 01 00 09 00 01 00 0a 00 +01 00 0b 00 01 00 0c 00 01 00 0d 00 01 00 0e 00 +01 00 0f 00 01 00 10 00 01 00 11 00 01 00 12 00 +01 00 13 00 01 00 14 00 01 00 15 00 01 00 16 00 +01 00 17 00 01 00 18 00 01 00 19 00 01 00 1a 00 +01 00 1b 00 01 00 1c 00 01 00 1d 00 01 00 1e 00 +01 00 1f 00 01 00 20 00 01 00 21 00 02 00 01 00 +02 00 02 00 02 00 03 00 02 00 04 00 02 00 06 00 +02 00 07 00 02 00 08 00 02 00 0a 00 02 00 0c 00 +02 00 0d 00 02 00 0e 00 02 00 0f 00 02 00 10 00 +02 00 11 00 02 00 12 00 02 00 13 00 02 00 14 00 +02 00 15 00 03 00 01 00 03 00 02 00 03 00 03 00 +03 00 06 00 03 00 07 00 03 00 08 00 03 00 09 00 +03 00 0a 00 03 00 0b 00 03 00 0c 00 04 00 01 00 +04 00 02 00 04 00 03 00 04 00 04 00 04 00 05 00 +04 00 07 00 04 00 08 00 04 00 09 00 04 00 0a 00 +04 00 0b 00 04 00 0c 00 04 00 0d 00 04 00 0e 00 +04 00 0f 00 04 00 10 00 04 00 11 00 04 00 12 00 +04 00 13 00 04 00 14 00 06 00 01 00 06 00 02 00 +06 00 03 00 08 00 01 00 08 00 02 00 09 00 01 00 +09 00 02 00 09 00 03 00 09 00 04 00 09 00 09 00 +09 00 0a 00 09 00 0b 00 0a 00 01 00 0a 00 02 00 +0a 00 03 00 0b 00 01 00 0b 00 02 00 0b 00 03 00 +0b 00 04 00 0c 00 01 00 0c 00 02 00 0c 00 03 00 +13 00 01 00 13 00 02 00 13 00 03 00 13 00 04 00 +13 00 05 00 13 00 06 00 13 00 07 00 13 00 08 00 +13 00 09 00 13 00 0a 00 13 00 0b 00 13 00 0c 00 +13 00 0d 00 13 00 0e 00 13 00 0f 00 13 00 10 00 +13 00 11 00 13 00 12 00 13 00 13 00 13 00 14 00 +13 00 15 00 13 00 16 00 13 00 17 00 13 00 18 00 +13 00 19 00 13 00 1a 00 13 00 1b 00 13 00 1c 00 +13 00 1d 00 13 00 1e 00 13 00 1f 00 13 00 20 00 +13 00 21 00 13 00 22 00 13 00 23 00 13 00 24 00 +13 00 25 00 13 00 26 00 13 00 27 00 13 00 28 00 +15 00 01 00 15 00 02 00 15 00 03 00 02 00 06 00 +03 00 04 00 03 00 05 00 09 00 05 00 09 00 06 00 +09 00 07 00 09 00 08 00 03 00 02 00 02 00 05 00 +04 00 06 00 04 00 02 00 02 00 09 00 02 00 0b 00 +05 00 00 +`; if (require.main === module) { - printBuffer(bufferFromWebText(exampleWebText), SNAC_01_0F); + printBuffer(bufferFromWebText(exSNAC_01_07), SNAC_01_07); }