Telegram Web K with changes to work inside I2P
https://web.telegram.i2p/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.4 KiB
134 lines
3.4 KiB
/* |
|
* https://github.com/morethanwords/tweb |
|
* Copyright (C) 2019-2021 Eduard Kuzmenko |
|
* https://github.com/morethanwords/tweb/blob/master/LICENSE |
|
*/ |
|
|
|
import pause from '../../../helpers/schedulers/pause'; |
|
import {DcId} from '../../../types'; |
|
import {logger, LogTypes} from '../../logger'; |
|
import type MTPNetworker from '../networker'; |
|
import MTTransport from './transport'; |
|
import Modes from '../../../config/modes'; |
|
|
|
// #if MTPROTO_AUTO |
|
import transportController from './controller'; |
|
// import networkStats from '../networkStats'; |
|
// #endif |
|
|
|
export default class HTTP implements MTTransport { |
|
public networker: MTPNetworker; |
|
private log: ReturnType<typeof logger>; |
|
|
|
private pending: Array<{ |
|
resolve: (body: Uint8Array) => void, |
|
reject: any, |
|
body: Uint8Array |
|
}> = []; |
|
private releasing: boolean; |
|
|
|
public connected: boolean; |
|
private destroyed: boolean; |
|
private debug: boolean; |
|
|
|
constructor(protected dcId: DcId, protected url: string, logSuffix: string) { |
|
this.debug = Modes.debug && false; |
|
|
|
let logTypes = LogTypes.Error | LogTypes.Log; |
|
if(this.debug) logTypes |= LogTypes.Debug; |
|
|
|
this.log = logger(`HTTP-${dcId}` + logSuffix, logTypes); |
|
this.log('constructor'); |
|
|
|
this.connected = false; |
|
} |
|
|
|
public _send(body: Uint8Array, mode?: RequestMode) { |
|
const length = body.length; |
|
this.debug && this.log.debug('-> body length to send:', length); |
|
|
|
// networkStats.addSent(this.dcId, length); |
|
return fetch(this.url, {method: 'POST', body, mode}).then((response) => { |
|
if(response.status !== 200 && !mode) { |
|
response.arrayBuffer().then((buffer) => { |
|
this.log.error('not 200', |
|
new TextDecoder('utf-8').decode(new Uint8Array(buffer))); |
|
}); |
|
|
|
throw response; |
|
} |
|
|
|
this.setConnected(true); |
|
|
|
// * test resending by dropping random request |
|
// if(Math.random() > .5) { |
|
// throw 'asd'; |
|
// } |
|
|
|
return response.arrayBuffer().then((buffer) => { |
|
// networkStats.addReceived(this.dcId, buffer.byteLength); |
|
return new Uint8Array(buffer); |
|
}); |
|
}, (err) => { |
|
this.setConnected(false); |
|
throw err; |
|
}); |
|
} |
|
|
|
private setConnected(connected: boolean) { |
|
if(this.connected === connected || this.destroyed) { |
|
return; |
|
} |
|
|
|
this.connected = connected; |
|
|
|
// #if MTPROTO_AUTO |
|
transportController.setTransportValue('https', connected); |
|
// #endif |
|
} |
|
|
|
public destroy() { |
|
this.setConnected(false); |
|
this.destroyed = true; |
|
this.pending.forEach((pending) => pending.reject()); |
|
this.pending.length = 0; |
|
} |
|
|
|
public send(body: Uint8Array) { |
|
if(this.networker) { |
|
return this._send(body); |
|
} else { |
|
const promise = new Promise<typeof body>((resolve, reject) => { |
|
this.pending.push({resolve, reject, body}); |
|
}); |
|
|
|
this.releasePending(); |
|
|
|
return promise; |
|
} |
|
} |
|
|
|
private async releasePending() { |
|
if(this.releasing) return; |
|
|
|
this.releasing = true; |
|
// this.log('-> messages to send:', this.pending.length); |
|
for(let i = 0; i < this.pending.length; ++i) { |
|
const pending = this.pending[i]; |
|
const {body, resolve} = pending; |
|
|
|
try { |
|
const result = await this._send(body); |
|
resolve(result); |
|
this.pending.splice(i, 1); |
|
} catch(err) { |
|
this.log.error('Send plain request error:', err); |
|
await pause(5000); |
|
} |
|
|
|
--i; |
|
} |
|
|
|
this.releasing = false; |
|
} |
|
}
|
|
|