mirror of
https://github.com/amigan/aim-oscar-server.git
synced 2024-11-22 04:29:47 -05:00
split out structures into their own files, try to make error codes
This commit is contained in:
parent
9d628233e1
commit
b699ef0ba0
9 changed files with 203 additions and 173 deletions
|
@ -1,5 +1,5 @@
|
||||||
import net from "net";
|
import net from "net";
|
||||||
import { FLAP, SNAC, TLV } from './structures';
|
import { FLAP, SNAC, TLV, TLVType } from './structures';
|
||||||
import { logDataStream } from './util';
|
import { logDataStream } from './util';
|
||||||
import { FLAGS_EMPTY } from './consts';
|
import { FLAGS_EMPTY } from './consts';
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ export default class Communicator {
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
// Start negotiating a connection
|
// Start negotiating a connection
|
||||||
|
console.log(FLAP, typeof FLAP);
|
||||||
const hello = new FLAP(0x01, 0, Buffer.from([0x00, 0x00, 0x00, 0x01]));
|
const hello = new FLAP(0x01, 0, Buffer.from([0x00, 0x00, 0x00, 0x01]));
|
||||||
this.send(hello);
|
this.send(hello);
|
||||||
}
|
}
|
||||||
|
@ -78,19 +79,18 @@ export default class Communicator {
|
||||||
const tlv = TLV.fromBuffer(message.payload.slice(4));
|
const tlv = TLV.fromBuffer(message.payload.slice(4));
|
||||||
console.log(tlv.toString());
|
console.log(tlv.toString());
|
||||||
|
|
||||||
switch (tlv.type) {
|
if (tlv.type === TLVType.GetServices) { // Requesting available services
|
||||||
case 0x06: // Requesting available services
|
// this is just a dword list of service families
|
||||||
// this is just a dword list of service families
|
const servicesOffered : Buffer[] = [];
|
||||||
const servicesOffered : Buffer[] = [];
|
Object.values(this.services).forEach((service) => {
|
||||||
Object.values(this.services).forEach((service) => {
|
servicesOffered.push(Buffer.from([0x00, service.family]));
|
||||||
servicesOffered.push(Buffer.from([0x00, service.family]));
|
});
|
||||||
});
|
const resp = new FLAP(2, this._getNewSequenceNumber(),
|
||||||
const resp = new FLAP(2, this._getNewSequenceNumber(),
|
new SNAC(0x01, 0x03, FLAGS_EMPTY, 0, [
|
||||||
new SNAC(0x01, 0x03, FLAGS_EMPTY, 0, [
|
Buffer.concat(servicesOffered),
|
||||||
Buffer.concat(servicesOffered),
|
]));
|
||||||
]));
|
this.send(resp);
|
||||||
this.send(resp);
|
return;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import BaseService from './base';
|
import BaseService from './base';
|
||||||
import Communicator from '../communicator';
|
import Communicator from '../communicator';
|
||||||
import { FLAP, SNAC, TLV } from '../structures';
|
import { FLAP, SNAC, TLV, ErrorCode, TLVType } from '../structures';
|
||||||
|
|
||||||
const { AIM_MD5_STRING, FLAGS_EMPTY } = require('../consts');
|
const { AIM_MD5_STRING, FLAGS_EMPTY } = require('../consts');
|
||||||
|
|
||||||
|
@ -26,13 +26,13 @@ export default class AuthorizationRegistrationService extends BaseService {
|
||||||
switch (message.payload.service) {
|
switch (message.payload.service) {
|
||||||
case 0x02: // Client login request (md5 login sequence)
|
case 0x02: // Client login request (md5 login sequence)
|
||||||
const tlvs = message.payload.tlvs;
|
const tlvs = message.payload.tlvs;
|
||||||
const clientNameTLV = tlvs.find((tlv) => tlv instanceof TLV && tlv.type === 0x03);
|
const clientNameTLV = tlvs.find((tlv) => tlv instanceof TLV && tlv.type === TLVType.ClientName);
|
||||||
if (!clientNameTLV || !(clientNameTLV instanceof TLV)) {
|
if (!clientNameTLV || !(clientNameTLV instanceof TLV)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("Attempting connection from", clientNameTLV.payload.toString('ascii'));
|
console.log("Attempting connection from", clientNameTLV.payload.toString('ascii'));
|
||||||
|
|
||||||
const userTLV = tlvs.find((tlv) => tlv instanceof TLV && tlv.type === 0x01);
|
const userTLV = tlvs.find((tlv) => tlv instanceof TLV && tlv.type === TLVType.User);
|
||||||
if (!userTLV || !(userTLV instanceof TLV)) {
|
if (!userTLV || !(userTLV instanceof TLV)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -42,15 +42,15 @@ export default class AuthorizationRegistrationService extends BaseService {
|
||||||
if (!users[username]) {
|
if (!users[username]) {
|
||||||
const authResp = new FLAP(2, this._getNewSequenceNumber(),
|
const authResp = new FLAP(2, this._getNewSequenceNumber(),
|
||||||
new SNAC(0x17, 0x03, FLAGS_EMPTY, 0, [
|
new SNAC(0x17, 0x03, FLAGS_EMPTY, 0, [
|
||||||
new TLV(0x0001, Buffer.from(username)), // username
|
TLV.forUsername(username), // username
|
||||||
new TLV(0x0008, Buffer.from([0x00, 0x04])) // incorrect nick/password
|
TLV.forError(ErrorCode.IncorrectNick) // incorrect nick/password
|
||||||
]));
|
]));
|
||||||
|
|
||||||
this.send(authResp);
|
this.send(authResp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const passwordHashTLV = tlvs.find((tlv) => tlv instanceof TLV && tlv.type === 0x25);
|
const passwordHashTLV = tlvs.find((tlv) => tlv instanceof TLV && tlv.type === TLVType.PasswordHash);
|
||||||
if (!passwordHashTLV || !(passwordHashTLV instanceof TLV)) {
|
if (!passwordHashTLV || !(passwordHashTLV instanceof TLV)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,8 @@ export default class AuthorizationRegistrationService extends BaseService {
|
||||||
console.log('Invalid password for', username);
|
console.log('Invalid password for', username);
|
||||||
const authResp = new FLAP(2, this._getNewSequenceNumber(),
|
const authResp = new FLAP(2, this._getNewSequenceNumber(),
|
||||||
new SNAC(0x17, 0x03, FLAGS_EMPTY, 0, [
|
new SNAC(0x17, 0x03, FLAGS_EMPTY, 0, [
|
||||||
new TLV(0x0001, Buffer.from(username)), // username
|
TLV.forUsername(username), // username
|
||||||
new TLV(0x0008, Buffer.from([0x00, 0x04])) // incorrect nick/password
|
TLV.forError(ErrorCode.IncorrectNick) // incorrect nick/password
|
||||||
]));
|
]));
|
||||||
this.send(authResp);
|
this.send(authResp);
|
||||||
return;
|
return;
|
||||||
|
@ -74,9 +74,9 @@ export default class AuthorizationRegistrationService extends BaseService {
|
||||||
|
|
||||||
const authResp = new FLAP(2, this._getNewSequenceNumber(),
|
const authResp = new FLAP(2, this._getNewSequenceNumber(),
|
||||||
new SNAC(0x17, 0x03, FLAGS_EMPTY, 0, [
|
new SNAC(0x17, 0x03, FLAGS_EMPTY, 0, [
|
||||||
new TLV(0x01, Buffer.from(username)), // username
|
TLV.forUsername(username), // username
|
||||||
new TLV(0x05, Buffer.from('10.0.1.29:5190')), // BOS address
|
TLV.forBOSAddress('10.0.1.29:5190'), // BOS address
|
||||||
new TLV(0x06, Buffer.from('im a cookie uwu')) // Authorization cookie
|
TLV.forCookie('im a cookie uwu') // Authorization cookie
|
||||||
]));
|
]));
|
||||||
|
|
||||||
this.send(authResp);
|
this.send(authResp);
|
||||||
|
|
|
@ -1,148 +0,0 @@
|
||||||
import assert from 'assert';
|
|
||||||
|
|
||||||
import { logDataStream } from './util';
|
|
||||||
|
|
||||||
export class TLV {
|
|
||||||
static fromBuffer(buf : Buffer) {
|
|
||||||
const type = buf.slice(0, 2).readInt16BE(0);
|
|
||||||
const len = buf.slice(2, 4).readInt16BE(0)
|
|
||||||
const payload = buf.slice(4, 4 + len);
|
|
||||||
|
|
||||||
return new TLV(type, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
public len : number;
|
|
||||||
|
|
||||||
constructor(public type : number, public payload : Buffer) {
|
|
||||||
this.type = type;
|
|
||||||
this.len = payload.length;
|
|
||||||
this.payload = payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return `TLV(0x${this.type.toString(16).padStart(2, '0')}, ${this.len}, ${this.payload.toString('ascii')})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
toBuffer() {
|
|
||||||
const TLVHeader = Buffer.alloc(4, 0, 'hex');
|
|
||||||
TLVHeader.writeUInt16BE(this.type);
|
|
||||||
TLVHeader.writeUInt16BE(this.len, 2);
|
|
||||||
return Buffer.concat([TLVHeader, this.payload]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class SNAC {
|
|
||||||
static fromBuffer(buf : Buffer, payloadLength = 0) {
|
|
||||||
assert(buf.length >= 10, 'Expected 10 bytes for SNAC header');
|
|
||||||
const family = buf.slice(0,2).readInt16BE(0);
|
|
||||||
const service = buf.slice(2,4).readInt16BE(0);
|
|
||||||
const flags = buf.slice(4, 6);
|
|
||||||
const requestID = buf.slice(6, 10).readInt32BE(0);
|
|
||||||
const tlvs : TLV[] = []; // SNACs can have multiple TLVs
|
|
||||||
|
|
||||||
let tlvsIdx = 10;
|
|
||||||
let cb = 0, cbLimit = 20; //circuit breaker
|
|
||||||
while (tlvsIdx < payloadLength && cb < cbLimit) {
|
|
||||||
const tlv = TLV.fromBuffer(buf.slice(tlvsIdx));
|
|
||||||
tlvs.push(tlv);
|
|
||||||
tlvsIdx += tlv.len + 4; // 4 bytes for TLV type + tlvs length
|
|
||||||
cb++;
|
|
||||||
}
|
|
||||||
if (cb === cbLimit) {
|
|
||||||
console.error('Application error, cb limit reached');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SNAC(family, service, flags, requestID, tlvs);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(public family : number, public service : number, public flags : Buffer, public requestID : number , public tlvs : Array<TLV | Buffer> = []) {
|
|
||||||
this.family = family;
|
|
||||||
this.service = service;
|
|
||||||
this.flags = flags;
|
|
||||||
this.requestID = requestID;
|
|
||||||
this.tlvs = tlvs;
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
return `SNAC(${this.family.toString(16)},${this.service.toString(16)}) #${this.requestID}\n ${this.tlvs}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
toBuffer() {
|
|
||||||
const SNACHeader = Buffer.alloc(10, 0, 'hex');
|
|
||||||
SNACHeader.writeUInt16BE(this.family);
|
|
||||||
SNACHeader.writeUInt16BE(this.service, 2);
|
|
||||||
SNACHeader.set(this.flags, 4);
|
|
||||||
SNACHeader.writeUInt32BE(this.requestID, 6);
|
|
||||||
|
|
||||||
const payload = this.tlvs.map((thing) => {
|
|
||||||
if (thing instanceof TLV) {
|
|
||||||
return thing.toBuffer();
|
|
||||||
}
|
|
||||||
return thing;
|
|
||||||
});
|
|
||||||
|
|
||||||
return Buffer.concat([SNACHeader, ...payload]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FLAP {
|
|
||||||
static fromBuffer(buf : Buffer) {
|
|
||||||
assert.equal(buf[0], 0x2a, 'Expected 0x2a at start of FLAP header');
|
|
||||||
assert(buf.length >= 6, 'Expected at least 6 bytes for FLAP header');
|
|
||||||
const channel = buf.readInt8(1);
|
|
||||||
const sequenceNumber = buf.slice(2,4).readInt16BE(0);
|
|
||||||
const payloadLength = buf.slice(4, 6).readInt16BE(0);
|
|
||||||
let payload : Buffer | SNAC = buf.slice(6, 6 + payloadLength);
|
|
||||||
|
|
||||||
if (channel === 2) {
|
|
||||||
payload = SNAC.fromBuffer(payload, payloadLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new FLAP(channel, sequenceNumber, payload)
|
|
||||||
}
|
|
||||||
|
|
||||||
payloadLength: number;
|
|
||||||
|
|
||||||
constructor(public channel: number, public sequenceNumber: number, public payload: Buffer | SNAC) {
|
|
||||||
this.channel = channel;
|
|
||||||
this.sequenceNumber = sequenceNumber;
|
|
||||||
|
|
||||||
this.payload = payload;
|
|
||||||
|
|
||||||
if (payload instanceof SNAC) {
|
|
||||||
this.payloadLength = payload.toBuffer().length;
|
|
||||||
} else {
|
|
||||||
this.payloadLength = payload.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
|
||||||
let payload = this.payload.toString();
|
|
||||||
if (this.payload instanceof Buffer) {
|
|
||||||
payload = logDataStream(this.payload).split('\n').join('\n ');
|
|
||||||
}
|
|
||||||
return `ch:${this.channel}, dn: ${this.sequenceNumber}, len: ${this.payloadLength}, payload:\n ${payload}`
|
|
||||||
}
|
|
||||||
|
|
||||||
toBuffer() {
|
|
||||||
const FLAPHeader = Buffer.alloc(6, 0, 'hex');
|
|
||||||
FLAPHeader.writeInt8(0x2a, 0);
|
|
||||||
FLAPHeader.writeInt8(this.channel, 1);
|
|
||||||
FLAPHeader.writeInt16BE(this.sequenceNumber, 2);
|
|
||||||
FLAPHeader.writeInt16BE(this.payloadLength, 4);
|
|
||||||
|
|
||||||
let payload = this.payload;
|
|
||||||
if (payload instanceof SNAC) {
|
|
||||||
payload = payload.toBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Buffer.concat([FLAPHeader, payload]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
TLV,
|
|
||||||
SNAC,
|
|
||||||
FLAP,
|
|
||||||
};
|
|
3
src/structures/ErrorCode.ts
Normal file
3
src/structures/ErrorCode.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const enum ErrorCode {
|
||||||
|
IncorrectNick = 0x04,
|
||||||
|
}
|
59
src/structures/FLAP.ts
Normal file
59
src/structures/FLAP.ts
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import assert from "assert"
|
||||||
|
|
||||||
|
import { SNAC } from "./SNAC";
|
||||||
|
import { logDataStream } from '../util';
|
||||||
|
|
||||||
|
export class FLAP {
|
||||||
|
static fromBuffer(buf : Buffer) {
|
||||||
|
assert.equal(buf[0], 0x2a, 'Expected 0x2a at start of FLAP header');
|
||||||
|
assert(buf.length >= 6, 'Expected at least 6 bytes for FLAP header');
|
||||||
|
const channel = buf.readInt8(1);
|
||||||
|
const sequenceNumber = buf.slice(2,4).readInt16BE(0);
|
||||||
|
const payloadLength = buf.slice(4, 6).readInt16BE(0);
|
||||||
|
let payload : Buffer | SNAC = buf.slice(6, 6 + payloadLength);
|
||||||
|
|
||||||
|
if (channel === 2) {
|
||||||
|
payload = SNAC.fromBuffer(payload, payloadLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FLAP(channel, sequenceNumber, payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadLength: number;
|
||||||
|
|
||||||
|
constructor(public channel: number, public sequenceNumber: number, public payload: Buffer | SNAC) {
|
||||||
|
this.channel = channel;
|
||||||
|
this.sequenceNumber = sequenceNumber;
|
||||||
|
|
||||||
|
this.payload = payload;
|
||||||
|
|
||||||
|
if (payload instanceof SNAC) {
|
||||||
|
this.payloadLength = payload.toBuffer().length;
|
||||||
|
} else {
|
||||||
|
this.payloadLength = payload.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
let payload = this.payload.toString();
|
||||||
|
if (this.payload instanceof Buffer) {
|
||||||
|
payload = logDataStream(this.payload).split('\n').join('\n ');
|
||||||
|
}
|
||||||
|
return `ch:${this.channel}, dn: ${this.sequenceNumber}, len: ${this.payloadLength}, payload:\n ${payload}`
|
||||||
|
}
|
||||||
|
|
||||||
|
toBuffer() {
|
||||||
|
const FLAPHeader = Buffer.alloc(6, 0, 'hex');
|
||||||
|
FLAPHeader.writeInt8(0x2a, 0);
|
||||||
|
FLAPHeader.writeInt8(this.channel, 1);
|
||||||
|
FLAPHeader.writeInt16BE(this.sequenceNumber, 2);
|
||||||
|
FLAPHeader.writeInt16BE(this.payloadLength, 4);
|
||||||
|
|
||||||
|
let payload = this.payload;
|
||||||
|
if (payload instanceof SNAC) {
|
||||||
|
payload = payload.toBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Buffer.concat([FLAPHeader, payload]);
|
||||||
|
}
|
||||||
|
}
|
57
src/structures/SNAC.ts
Normal file
57
src/structures/SNAC.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import assert from "assert";
|
||||||
|
import { TLV } from "./TLV";
|
||||||
|
|
||||||
|
export class SNAC {
|
||||||
|
static fromBuffer(buf : Buffer, payloadLength = 0) {
|
||||||
|
assert(buf.length >= 10, 'Expected 10 bytes for SNAC header');
|
||||||
|
const family = buf.slice(0,2).readInt16BE(0);
|
||||||
|
const service = buf.slice(2,4).readInt16BE(0);
|
||||||
|
const flags = buf.slice(4, 6);
|
||||||
|
const requestID = buf.slice(6, 10).readInt32BE(0);
|
||||||
|
const tlvs : TLV[] = []; // SNACs can have multiple TLVs
|
||||||
|
|
||||||
|
let tlvsIdx = 10;
|
||||||
|
let cb = 0, cbLimit = 20; //circuit breaker
|
||||||
|
while (tlvsIdx < payloadLength && cb < cbLimit) {
|
||||||
|
const tlv = TLV.fromBuffer(buf.slice(tlvsIdx));
|
||||||
|
tlvs.push(tlv);
|
||||||
|
tlvsIdx += tlv.length + 4; // 4 bytes for TLV type + tlvs length
|
||||||
|
cb++;
|
||||||
|
}
|
||||||
|
if (cb === cbLimit) {
|
||||||
|
console.error('Application error, cb limit reached');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SNAC(family, service, flags, requestID, tlvs);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(public family : number, public service : number, public flags : Buffer, public requestID : number , public tlvs : Array<TLV | Buffer> = []) {
|
||||||
|
this.family = family;
|
||||||
|
this.service = service;
|
||||||
|
this.flags = flags;
|
||||||
|
this.requestID = requestID;
|
||||||
|
this.tlvs = tlvs;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `SNAC(${this.family.toString(16)},${this.service.toString(16)}) #${this.requestID}\n ${this.tlvs}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
toBuffer() {
|
||||||
|
const SNACHeader = Buffer.alloc(10, 0, 'hex');
|
||||||
|
SNACHeader.writeUInt16BE(this.family);
|
||||||
|
SNACHeader.writeUInt16BE(this.service, 2);
|
||||||
|
SNACHeader.set(this.flags, 4);
|
||||||
|
SNACHeader.writeUInt32BE(this.requestID, 6);
|
||||||
|
|
||||||
|
const payload = this.tlvs.map((thing) => {
|
||||||
|
if (thing instanceof TLV) {
|
||||||
|
return thing.toBuffer();
|
||||||
|
}
|
||||||
|
return thing;
|
||||||
|
});
|
||||||
|
|
||||||
|
return Buffer.concat([SNACHeader, ...payload]);
|
||||||
|
}
|
||||||
|
}
|
54
src/structures/TLV.ts
Normal file
54
src/structures/TLV.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import {ErrorCode} from "./ErrorCode";
|
||||||
|
|
||||||
|
export const enum TLVType {
|
||||||
|
User = 0x01,
|
||||||
|
ClientName = 0x03,
|
||||||
|
GetServices = 0x06,
|
||||||
|
PasswordHash = 0x25,
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TLV {
|
||||||
|
get length() : number {
|
||||||
|
return this.payload.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromBuffer(buf : Buffer) {
|
||||||
|
const type = buf.slice(0, 2).readInt16BE(0) as TLVType;
|
||||||
|
const len = buf.slice(2, 4).readInt16BE(0)
|
||||||
|
const payload = buf.slice(4, 4 + len);
|
||||||
|
|
||||||
|
return new TLV(type, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
static forUsername(username : string) : TLV {
|
||||||
|
return new TLV(0x01, Buffer.from(username));
|
||||||
|
}
|
||||||
|
|
||||||
|
static forBOSAddress(address : string ) : TLV {
|
||||||
|
return new TLV(0x05, Buffer.from(address));
|
||||||
|
}
|
||||||
|
|
||||||
|
static forCookie(cookie : string) : TLV {
|
||||||
|
return new TLV(0x06, Buffer.from(cookie));
|
||||||
|
}
|
||||||
|
|
||||||
|
static forError(errorCode : ErrorCode) : TLV {
|
||||||
|
return new TLV(0x08, Buffer.from([0x00, errorCode]));
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(public type : TLVType, public payload : Buffer) {
|
||||||
|
this.type = type;
|
||||||
|
this.payload = payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `TLV(0x${this.type.toString(16).padStart(2, '0')}, ${this.length}, ${this.payload.toString('ascii')})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
toBuffer() {
|
||||||
|
const TLVHeader = Buffer.alloc(4, 0, 'hex');
|
||||||
|
TLVHeader.writeUInt16BE(this.type);
|
||||||
|
TLVHeader.writeUInt16BE(this.length, 2);
|
||||||
|
return Buffer.concat([TLVHeader, this.payload]);
|
||||||
|
}
|
||||||
|
}
|
4
src/structures/index.ts
Normal file
4
src/structures/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export * from "./ErrorCode";
|
||||||
|
export * from "./TLV";
|
||||||
|
export * from "./SNAC";
|
||||||
|
export * from "./FLAP";
|
|
@ -2,6 +2,7 @@
|
||||||
"extends": "@tsconfig/node14/tsconfig.json",
|
"extends": "@tsconfig/node14/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"preserveConstEnums": true,
|
"preserveConstEnums": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
},
|
},
|
||||||
"include": ["src/**/*"],
|
"include": ["src/**/*"],
|
||||||
|
|
Loading…
Reference in a new issue