Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 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 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | import dbg from 'debug';
import { ServerContextHandleManager } from './ServerContextHandleManager';
import { CtxtHandle } from '../../../lib/api';
import { SSOMethod } from '../interfaces';
const debug = dbg('node-expose-sspi:schManager');
type IPromiseFn = (value?: any) => void;
interface AuthItem {
resolve?: IPromiseFn;
reject?: IPromiseFn;
timeout: NodeJS.Timeout;
}
const TOO_LATE_ERROR_MSG = 'too many concurrent connections.';
export class SCHMWithSync extends ServerContextHandleManager {
/**
* The authentication currently being processed.
*
* @private
* @type {AuthItem}
* @memberof SCHMWithSync
*/
private authItem: AuthItem | undefined;
/**
* The queue of other authentication that are waiting.
*
* @private
* @type {AuthItem[]}
* @memberof SCHMWithSync
*/
private queue: AuthItem[] = [];
private serverContextHandle: CtxtHandle | undefined;
private method!: SSOMethod;
constructor(private delayMax = 20000) {
super();
}
waitForReleased(): Promise<void> {
return new Promise((resolve, reject) => {
debug('waitForReleased: start promise');
const timeout = setTimeout(() => {
this.interrupt();
}, this.delayMax);
// if nobody else is currently authenticating then go now.
if (this.authItem === undefined) {
debug('waitForReleased: we can start now.');
this.authItem = { timeout };
return resolve();
}
debug(
'someone is currently authenticating, go in the queue and wait for your turn.'
);
this.queue.push({ resolve, reject, timeout });
debug('queue length', this.queue.length);
});
}
getMethod(): SSOMethod {
return this.method;
}
setMethod(ssoMethod: SSOMethod): void {
this.method = ssoMethod;
}
getHandle(): CtxtHandle | undefined {
return this.serverContextHandle;
}
setHandle(contextHandle: CtxtHandle): void {
this.serverContextHandle = contextHandle;
}
release(): void {
if (this.authItem) {
clearTimeout(this.authItem.timeout);
}
this.serverContextHandle = undefined;
this.authItem = undefined;
if (this.queue.length > 0) {
// it means another client B was waiting for authenticating.
// so we start authenticating this client B.
this.authItem = this.queue.shift();
debug('releasing. queue length', this.queue.length);
if (this.authItem?.resolve) {
this.authItem.resolve();
}
}
}
/**
* after timeout, all the queue is removed and rejected.
* does not go to its final state before timeout.
*
*
* @param {AuthItem} authItem
* @returns
* @memberof ServerContextHandleManager
*/
interrupt(): void {
while (this.queue.length > 0) {
const ai = this.queue.pop();
if (ai) {
clearTimeout(ai.timeout);
if (ai.reject) {
ai.reject(TOO_LATE_ERROR_MSG);
}
}
}
this.authItem = undefined;
this.serverContextHandle = undefined;
}
}
|