Skip to content

Commit

Permalink
WIP.
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurschreiber committed Oct 1, 2023
1 parent 4702b03 commit b78d2dd
Show file tree
Hide file tree
Showing 9 changed files with 282 additions and 159 deletions.
4 changes: 2 additions & 2 deletions src/token/colmetadata-token-parser.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import type { BufferList } from 'bl/BufferList';
import metadataParse, { readMetadata, type Metadata } from '../metadata-parser';
import { readMetadata, type Metadata } from '../metadata-parser';

import Parser, { type ParserOptions } from './stream-parser';
import { ColMetadataToken } from './token';
import { NotEnoughDataError, Result, readBVarChar, readUInt16LE, readUInt8, readUsVarChar } from './helpers';
import { NotEnoughDataError, type Result, readBVarChar, readUInt16LE, readUInt8, readUsVarChar } from './helpers';

export interface ColumnMetadata extends Metadata {
/**
Expand Down
72 changes: 42 additions & 30 deletions src/token/fedauth-info-parser.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,61 @@
import Parser, { type ParserOptions } from './stream-parser';
import type { BufferList } from 'bl/BufferList';
import { NotEnoughDataError, readUInt16LE, type Result } from './helpers';
import { type ParserOptions } from './stream-parser';
import { FedAuthInfoToken } from './token';

const FEDAUTHINFOID = {
STSURL: 0x01,
SPN: 0x02
};

function fedAuthInfoParser(parser: Parser, _options: ParserOptions, callback: (token: FedAuthInfoToken) => void) {
parser.readUInt32LE((tokenLength) => {
parser.readBuffer(tokenLength, (data) => {
let spn: string | undefined, stsurl: string | undefined;
function readFedAuthInfo(data: Buffer): { spn: string | undefined, stsurl: string | undefined } {
let offset = 0;
let spn, stsurl;

let offset = 0;
const countOfInfoIDs = data.readUInt32LE(offset);
offset += 4;

const countOfInfoIDs = data.readUInt32LE(offset);
offset += 4;
for (let i = 0; i < countOfInfoIDs; i++) {
const fedauthInfoID = data.readUInt8(offset);
offset += 1;

for (let i = 0; i < countOfInfoIDs; i++) {
const fedauthInfoID = data.readUInt8(offset);
offset += 1;
const fedAuthInfoDataLen = data.readUInt32LE(offset);
offset += 4;

const fedAuthInfoDataLen = data.readUInt32LE(offset);
offset += 4;
const fedAuthInfoDataOffset = data.readUInt32LE(offset);
offset += 4;

const fedAuthInfoDataOffset = data.readUInt32LE(offset);
offset += 4;
switch (fedauthInfoID) {
case FEDAUTHINFOID.SPN:
spn = data.toString('ucs2', fedAuthInfoDataOffset, fedAuthInfoDataOffset + fedAuthInfoDataLen);
break;

switch (fedauthInfoID) {
case FEDAUTHINFOID.SPN:
spn = data.toString('ucs2', fedAuthInfoDataOffset, fedAuthInfoDataOffset + fedAuthInfoDataLen);
break;
case FEDAUTHINFOID.STSURL:
stsurl = data.toString('ucs2', fedAuthInfoDataOffset, fedAuthInfoDataOffset + fedAuthInfoDataLen);
break;

case FEDAUTHINFOID.STSURL:
stsurl = data.toString('ucs2', fedAuthInfoDataOffset, fedAuthInfoDataOffset + fedAuthInfoDataLen);
break;
// ignoring unknown fedauthinfo options
default:
break;
}
}

// ignoring unknown fedauthinfo options
default:
break;
}
}
return { spn, stsurl };
}

function fedAuthInfoParser(buf: Buffer | BufferList, offset: number, _options: ParserOptions): Result<FedAuthInfoToken> {
let tokenLength;
({ offset, value: tokenLength } = readUInt16LE(buf, offset));

if (buf.length < offset + tokenLength) {
throw new NotEnoughDataError(offset + tokenLength);
}

const data = buf.slice(offset, offset + tokenLength);
offset += tokenLength;

callback(new FedAuthInfoToken(spn, stsurl));
});
});
const { spn, stsurl } = readFedAuthInfo(data);
return { value: new FedAuthInfoToken(spn, stsurl), offset };
}

export default fedAuthInfoParser;
Expand Down
10 changes: 10 additions & 0 deletions src/token/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ export function readUInt32LE(buf: Buffer | BufferList, offset: number): Result<n
return { value: buf.readUInt32LE(offset), offset: offset + 4 };
}

export function readUInt32BE(buf: Buffer | BufferList, offset: number): Result<number> {
offset = +offset;

if (buf.length < offset + 4) {
throw new NotEnoughDataError(offset + 4);
}

return { value: buf.readUInt32BE(offset), offset: offset + 4 };
}

export function readUInt40LE(buf: Buffer | BufferList, offset: number): Result<number> {
offset = +offset;

Expand Down
81 changes: 50 additions & 31 deletions src/token/loginack-token-parser.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,64 @@
import Parser, { type ParserOptions } from './stream-parser';
import { type ParserOptions } from './stream-parser';

import { LoginAckToken } from './token';

import { versionsByValue as versions } from '../tds-versions';
import type { BufferList } from 'bl/BufferList';
import { NotEnoughDataError, readBVarChar, readUInt16LE, readUInt32BE, readUInt8, type Result } from './helpers';

const interfaceTypes: { [key: number]: string } = {
0: 'SQL_DFLT',
1: 'SQL_TSQL'
};

function loginAckParser(parser: Parser, _options: ParserOptions, callback: (token: LoginAckToken) => void) {
function loginAckParser(buf: Buffer | BufferList, offset: number, _options: ParserOptions): Result<LoginAckToken> {
// length
parser.readUInt16LE(() => {
parser.readUInt8((interfaceNumber) => {
const interfaceType = interfaceTypes[interfaceNumber];
parser.readUInt32BE((tdsVersionNumber) => {
const tdsVersion = versions[tdsVersionNumber];
parser.readBVarChar((progName) => {
parser.readUInt8((major) => {
parser.readUInt8((minor) => {
parser.readUInt8((buildNumHi) => {
parser.readUInt8((buildNumLow) => {
callback(new LoginAckToken({
interface: interfaceType,
tdsVersion: tdsVersion,
progName: progName,
progVersion: {
major: major,
minor: minor,
buildNumHi: buildNumHi,
buildNumLow: buildNumLow
}
}));
});
});
});
});
});
});
});
});
let tokenLength;
({ offset, value: tokenLength } = readUInt16LE(buf, offset));

if (buf.length < offset + tokenLength) {
throw new NotEnoughDataError(offset + tokenLength);
}

let interfaceNumber;
({ offset, value: interfaceNumber } = readUInt8(buf, offset));

const interfaceType = interfaceTypes[interfaceNumber];

let tdsVersionNumber;
({ offset, value: tdsVersionNumber } = readUInt32BE(buf, offset));

const tdsVersion = versions[tdsVersionNumber];

let progName;
({ offset, value: progName } = readBVarChar(buf, offset));

let major;
({ offset, value: major } = readUInt8(buf, offset));

let minor;
({ offset, value: minor } = readUInt8(buf, offset));

let buildNumHi;
({ offset, value: buildNumHi } = readUInt8(buf, offset));

let buildNumLow;
({ offset, value: buildNumLow } = readUInt8(buf, offset));

return {
value: new LoginAckToken({
interface: interfaceType,
tdsVersion: tdsVersion,
progName: progName,
progVersion: {
major: major,
minor: minor,
buildNumHi: buildNumHi,
buildNumLow: buildNumLow
}
}),
offset
};
}

export default loginAckParser;
Expand Down
37 changes: 17 additions & 20 deletions src/token/order-token-parser.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
// s2.2.7.14
import Parser, { type ParserOptions } from './stream-parser';
import type { BufferList } from 'bl/BufferList';
import { type ParserOptions } from './stream-parser';

import { OrderToken } from './token';
import { NotEnoughDataError, readUInt16LE, type Result } from './helpers';

function orderParser(parser: Parser, _options: ParserOptions, callback: (token: OrderToken) => void) {
parser.readUInt16LE((length) => {
const columnCount = length / 2;
const orderColumns: number[] = [];
function orderParser(buf: Buffer | BufferList, offset: number, _options: ParserOptions): Result<OrderToken> {
// length
let tokenLength;
({ offset, value: tokenLength } = readUInt16LE(buf, offset));

let i = 0;
function next(done: () => void) {
if (i === columnCount) {
return done();
}
if (buf.length < offset + tokenLength) {
throw new NotEnoughDataError(offset + tokenLength);
}

parser.readUInt16LE((column) => {
orderColumns.push(column);
const orderColumns: number[] = [];

i++;
for (let i = 0; i < tokenLength; i += 2) {
let column;
({ offset, value: column } = readUInt16LE(buf, offset));

next(done);
});
}
orderColumns.push(column);
}

next(() => {
callback(new OrderToken(orderColumns));
});
});
return { value: new OrderToken(orderColumns), offset };
}

export default orderParser;
Expand Down
28 changes: 7 additions & 21 deletions src/token/returnstatus-token-parser.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,14 @@
// s2.2.7.16
import { NotEnoughDataError, readInt32LE } from './helpers';
import Parser, { type ParserOptions } from './stream-parser';
import type { BufferList } from 'bl/BufferList';
import { readInt32LE, type Result } from './helpers';
import { type ParserOptions } from './stream-parser';

import { ReturnStatusToken } from './token';

function returnStatusParser(parser: Parser, _options: ParserOptions, callback: (token: ReturnStatusToken) => void) {
(async (parser, callback) => {
while (true) {
let value, offset;
try {
({ value, offset } = readInt32LE(parser.buffer, parser.position));
} catch (err) {
if (err instanceof NotEnoughDataError) {
await parser.streamBuffer.waitForChunk();
continue;
}

throw err;
}

parser.position = offset;
return callback(new ReturnStatusToken(value));
}
})(parser, callback);
function returnStatusParser(buf: Buffer | BufferList, offset: number, _options: ParserOptions): Result<ReturnStatusToken> {
let value;
({ value, offset } = readInt32LE(buf, offset));
return { value: new ReturnStatusToken(value), offset };
}

export default returnStatusParser;
Expand Down
Loading

0 comments on commit b78d2dd

Please sign in to comment.