Skip to content

Commit d16e414

Browse files
peter xiepeter xie
authored andcommitted
v1.0.0RC
1 parent 6ced952 commit d16e414

File tree

14 files changed

+1031
-325
lines changed

14 files changed

+1031
-325
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
This is QTGATE client software install build
88
QTGATE is a service that use email IMAP protocol to make a virtual tunnel that exchanges packets between clients and servers. [QTGATE](https://www.qtgate.com).
99
The excellent point is QTGATE exchanges data by email account, client and server do not need IP address. Nobody know where you from even QTGATE system.
10-
QTGate have a local proxy server support HTTP HTTPS SOCKS 4,4a,5. All other devices can use QTGate via ths local proxy server.
10+
QTGate have a local proxy server support HTTP HTTPS SOCKS 4,4a,5. All other devices can use QTGate via this local proxy server.
1111

1212
這是 QTGATE 客戶端 install.
1313
QTGATE是一种安全通讯手段,通过eMail的IMAP协议建立一个虚拟的专用通道,连接客户端和代理服务器,它的奇妙之处在于客户端和服务器彼此不用知道相互的IP地址,而是通过共用一个eMail账号进行数据交换,QTGATE系统把VPN包加密后,利用IMAP进行通讯,能最大限度的保护您的网络通讯不被检测和干扰,建立一个私密的网络安全环境。

app/imap.js

Lines changed: 136 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const Crypto = require("crypto");
2727
const path_1 = require("path");
2828
const os_1 = require("os");
2929
const timers_1 = require("timers");
30+
const buffer_1 = require("buffer");
3031
const MAX_INT = 9007199254740992;
3132
const debug = true;
3233
const QTGateFolder = path_1.join(os_1.homedir(), '.QTGate');
@@ -53,7 +54,7 @@ class ImapServerSwitchStream extends Stream.Transform {
5354
this.eachMail = eachMail;
5455
this.exitWithDeleteBox = exitWithDeleteBox;
5556
this.debug = debug;
56-
this._buffer = Buffer.alloc(0);
57+
this._buffer = buffer_1.Buffer.alloc(0);
5758
this.Tag = null;
5859
this.cmd = null;
5960
this.callback = false;
@@ -63,7 +64,7 @@ class ImapServerSwitchStream extends Stream.Transform {
6364
this.idleCallBack = null;
6465
this.waitLogout = false;
6566
this.waitLogoutCallBack = null;
66-
this._newMailChunk = Buffer.alloc(0);
67+
this._newMailChunk = buffer_1.Buffer.alloc(0);
6768
this.idleResponsrTime = null;
6869
this.canDoLogout = false;
6970
this.ready = false;
@@ -170,7 +171,7 @@ class ImapServerSwitchStream extends Stream.Transform {
170171
//console.log ('************************************** ImapServerSwitchStream _transform chunk **************************************')
171172
//console.log ( chunk.toString ())
172173
//console.log ('************************************** ImapServerSwitchStream _transform chunk **************************************')
173-
this._buffer = Buffer.concat([this._buffer, chunk]);
174+
this._buffer = buffer_1.Buffer.concat([this._buffer, chunk]);
174175
const doLine = () => {
175176
const __CallBack = () => {
176177
let index = -1;
@@ -234,6 +235,10 @@ class ImapServerSwitchStream extends Stream.Transform {
234235
if (this.waitLogout) {
235236
return this.logout_process(this.waitLogoutCallBack);
236237
}
238+
if (/^inbox$/i.test(this.imapServer.listenFolder)) {
239+
this.canDoLogout = this.ready = true;
240+
return this.imapServer.emit('ready');
241+
}
237242
if (newMail) {
238243
return this.doNewMail();
239244
}
@@ -399,7 +404,6 @@ class ImapServerSwitchStream extends Stream.Transform {
399404
login(text, cmdArray, next, _callback) {
400405
this.doCommandCallback = (err) => {
401406
if (!err) {
402-
saveLog(`login this.doCommandCallback no err `);
403407
return this.capability();
404408
}
405409
return this.imapServer.destroyAll(err);
@@ -686,7 +690,7 @@ class ImapServerSwitchStream extends Stream.Transform {
686690
console.log(`logout_process doLogout()`);
687691
if (this.imapServer.listenFolder && this.imapServer.deleteBoxWhenEnd) {
688692
return Async.series([
689-
next => this.deleteBox(next),
693+
next => { /^INBOX$/i.test(this.imapServer.listenFolder) ? next() : this.deleteBox(next); },
690694
next => this._logout(next)
691695
], callback);
692696
}
@@ -766,12 +770,6 @@ class qtGateImap extends Event.EventEmitter {
766770
this.once(`error`, err => {
767771
saveLog(`qtGateImap on error [${err.messag}]`);
768772
});
769-
/*
770-
process.once ( 'uncaughtException', err => {
771-
console.log ( err )
772-
this.destroyAll ( err )
773-
})
774-
*/
775773
}
776774
get TagCount() {
777775
if (++this.tagcount < MAX_INT)
@@ -856,9 +854,9 @@ class qtGateImapwrite extends qtGateImap {
856854
return _callback(new Error('not ready!'));
857855
if (this.canAppend) {
858856
this.canAppend = false;
859-
return this.imapStream.append(text, err => {
857+
return this.imapStream.append(text, (err, code) => {
860858
this.canAppend = true;
861-
_callback(err);
859+
_callback(err, code);
862860
const uu = this.appendPool.pop();
863861
if (uu) {
864862
return this.append(uu.text, uu.callback);
@@ -876,10 +874,21 @@ exports.qtGateImapwrite = qtGateImapwrite;
876874
class qtGateImapRead extends qtGateImap {
877875
constructor(IMapConnect, listenFolder, isEachMail, deleteBoxWhenEnd, newMail) {
878876
super(IMapConnect, listenFolder, isEachMail, deleteBoxWhenEnd, null, debug, newMail);
877+
this.openBox = false;
879878
this.once('ready', () => {
879+
this.openBox = true;
880880
console.log(`qtGateImapRead [${listenFolder}] ready`);
881881
});
882882
}
883+
fetchAndDelete(Uid, CallBack) {
884+
if (!this.openBox)
885+
return CallBack(new Error('not ready!'));
886+
return Async.series([
887+
next => this.imapStream.fetch(Uid, next),
888+
next => this.imapStream.flagsDeleted(Uid, next),
889+
next => this.imapStream.expunge(next)
890+
], CallBack);
891+
}
883892
}
884893
exports.qtGateImapRead = qtGateImapRead;
885894
exports.getMailAttached = (email) => {
@@ -889,60 +898,86 @@ exports.getMailAttached = (email) => {
889898
return null;
890899
}
891900
const attachment = email.slice(attachmentStart + 4);
892-
return Buffer.from(attachment.toString(), 'base64');
901+
return buffer_1.Buffer.from(attachment.toString(), 'base64');
893902
};
894903
exports.imapBasicTest = (IMapConnect, CallBack) => {
895904
saveLog(`start imapBasicTest imap [${JSON.stringify(IMapConnect)}]`);
896905
let callbackCall = false;
897-
let startTime = null;
898-
let wImap = null;
899-
const listenFolder = Crypto.randomBytes(20).toString('hex');
900-
const ramdomText = Crypto.randomBytes(20);
901-
const timeout = timers_1.setTimeout(() => {
902-
if (rImap) {
903-
rImap.logout();
904-
}
905-
rImap = null;
906-
if (wImap) {
907-
wImap.logout();
908-
}
909-
wImap = null;
910-
doCallBack(new Error('timeout'), null);
911-
}, 15000);
906+
let append = false;
907+
let timeout = null;
908+
const listenFolder = 'INBOX';
909+
let getText = false;
910+
const ramdomText = Crypto.randomBytes(1024 * 100);
912911
const doCallBack = (err, ret) => {
913912
if (!callbackCall) {
914913
callbackCall = true;
915914
timers_1.clearTimeout(timeout);
916915
return CallBack(err, ret);
917916
}
918917
};
919-
let rImap = new qtGateImapRead(IMapConnect, listenFolder, true, true, () => {
920-
});
921-
rImap.once('ready', () => {
922-
console.log(`imapBasicTest rImap.once ( 'ready' )`);
923-
rImap.logout();
924-
rImap = null;
925-
wImap = new qtGateImapwrite(IMapConnect, listenFolder);
926-
wImap.once('ready', () => {
927-
console.log(`imapBasicTest wImap.once ( 'ready' )`);
928-
startTime = new Date().getTime();
929-
wImap.append(ramdomText.toString('base64'), (err, info) => {
930-
if (err) {
931-
console.log(` imapBasicTest wImap.append err`, err);
932-
}
933-
else {
934-
console.log(`imapBasicTest wImap.append success [${info}]`);
918+
let wImap = new qtGateImapwrite(IMapConnect, listenFolder);
919+
const doCatchMail = (id, _CallBack) => {
920+
let didFatch = false;
921+
let err = null;
922+
let rImap = new qtGateImapRead(IMapConnect, listenFolder, false, false, mail => {
923+
saveLog(`new mail`);
924+
const attach = exports.getMailAttached(mail);
925+
if (!attach) {
926+
err = new Error(`imapAccountTest ERROR: can't read attachment!`);
927+
}
928+
else if (ramdomText.compare(attach) !== 0) {
929+
err = new Error(`imapAccountTest ERROR: attachment changed!`);
930+
}
931+
else {
932+
getText = true;
933+
}
934+
});
935+
rImap.once('ready', () => {
936+
rImap.fetchAndDelete(id, _err => {
937+
didFatch = true;
938+
if (_err) {
939+
err = _err;
935940
}
936-
wImap.logout();
937-
wImap = null;
941+
saveLog(`rImap.fetchAndDelete finished by err [${err && err.message ? err.message : null}]`);
942+
rImap.logout();
943+
rImap = null;
938944
});
939945
});
946+
rImap.once('end', err => {
947+
if (!didFatch) {
948+
saveLog(`doCatchMail rImap.once end but didFatch = false try again!`);
949+
return doCatchMail(id, _CallBack);
950+
}
951+
_CallBack(err, getText);
952+
});
953+
};
954+
wImap.once('ready', () => {
955+
saveLog(`imapBasicTest wImap.once ( 'ready' )`);
956+
wImap.append(ramdomText.toString('base64'), (err, code) => {
957+
append = true;
958+
if (err) {
959+
saveLog(`wImap.append got error [${err.message}]`);
960+
return doCallBack(err, null);
961+
}
962+
if (!code) {
963+
saveLog(`wImap.append got no append id!`);
964+
return doCallBack(new Error(`no append id!`), null);
965+
}
966+
const uid = code.substring(code.search(/\[/), code.search(/\]/)).split(' ')[2];
967+
wImap.logout();
968+
wImap = null;
969+
doCatchMail(uid, doCallBack);
970+
});
940971
});
941-
rImap.once('end', err => {
942-
doCallBack(err, null);
972+
wImap.once('end', err => {
973+
if (!append && !err) {
974+
saveLog(`imapBasicTest wImap.once ( 'end', err = [${err && err.message ? err.message : 'undefine'}] but !startTime do imapBasicTest again! )`);
975+
return exports.imapBasicTest(IMapConnect, CallBack);
976+
}
977+
return doCallBack(err, null);
943978
});
944-
rImap.once('error', err => {
945-
doCallBack(err, null);
979+
wImap.once('error', err => {
980+
return doCallBack(err, null);
946981
});
947982
};
948983
exports.imapAccountTest = (IMapConnect, CallBack) => {
@@ -952,17 +987,11 @@ exports.imapAccountTest = (IMapConnect, CallBack) => {
952987
let wImap = null;
953988
const listenFolder = Uuid.v4();
954989
const ramdomText = Crypto.randomBytes(20);
955-
const timeout = timers_1.setTimeout(() => {
956-
if (rImap) {
957-
rImap.logout();
958-
}
959-
if (wImap) {
960-
wImap.logout();
961-
}
962-
doCallBack(new Error('timeout'), null);
963-
}, 15000);
990+
let timeout = null;
964991
const doCallBack = (err, ret) => {
965992
if (!callbackCall) {
993+
console.trace('imapAccountTest doCallBack');
994+
saveLog(`imapAccountTest doing callback err [${err && err.messgae ? err.messgae : `undefine `}] ret [${ret ? ret : 'undefine'}]`);
966995
callbackCall = true;
967996
timers_1.clearTimeout(timeout);
968997
return CallBack(err, ret);
@@ -972,41 +1001,67 @@ exports.imapAccountTest = (IMapConnect, CallBack) => {
9721001
rImap.logout();
9731002
rImap = null;
9741003
const attach = exports.getMailAttached(mail);
975-
console.log(`rImap on new mail!`, attach);
976-
if (!attach && !callbackCall) {
1004+
saveLog(`test rImap on new mail! `);
1005+
if (!attach) {
9771006
return doCallBack(new Error(`imapAccountTest ERROR: can't read attachment!`), null);
9781007
}
979-
if (ramdomText.compare(attach) !== 0 && !callbackCall) {
1008+
if (ramdomText.compare(attach) !== 0) {
9801009
return doCallBack(new Error(`imapAccountTest ERROR: attachment changed!`), null);
9811010
}
9821011
return doCallBack(null, new Date().getTime() - startTime);
9831012
});
9841013
rImap.once('ready', () => {
985-
console.log(`rImap.once ( 'ready' )`);
1014+
saveLog(`rImap.once ( 'ready' ) do new qtGateImapwrite`);
9861015
wImap = new qtGateImapwrite(IMapConnect, listenFolder);
1016+
let sendMessage = false;
9871017
wImap.once('ready', () => {
988-
console.log(`wImap.once ( 'ready' )`);
989-
startTime = new Date().getTime();
1018+
saveLog(`wImap.once ( 'ready' )`);
9901019
wImap.append(ramdomText.toString('base64'), err => {
991-
if (err) {
992-
console.log(`wImap.append err`, err);
993-
}
994-
else {
995-
console.log(`wImap.append success`);
996-
}
1020+
sendMessage = true;
9971021
wImap.logout();
9981022
wImap = null;
1023+
if (err) {
1024+
rImap.logout();
1025+
rImap = null;
1026+
saveLog(`wImap.append err [${err.message ? err.message : 'none err.message'}]`);
1027+
return doCallBack(err, null);
1028+
}
1029+
startTime = new Date().getTime();
1030+
timeout = timers_1.setTimeout(() => {
1031+
if (rImap) {
1032+
rImap.logout();
1033+
}
1034+
if (wImap) {
1035+
wImap.logout();
1036+
}
1037+
saveLog(`imapAccountTest doing timeout`);
1038+
doCallBack(new Error('timeout'), null);
1039+
}, pingPongTimeOut);
9991040
});
10001041
});
1042+
wImap.once('end', () => {
1043+
if (!sendMessage) {
1044+
rImap.logout();
1045+
rImap = null;
1046+
saveLog(`wImap.once ( 'end') before send message! do imapAccountTest again!`);
1047+
return exports.imapAccountTest(IMapConnect, CallBack);
1048+
}
1049+
});
10011050
});
10021051
rImap.once('end', err => {
1003-
doCallBack(err, null);
1052+
saveLog(`rImap.once ( 'end' ) [${err && err.message ? err.message : 'err = undefine'}]`);
1053+
if (!callbackCall && !err) {
1054+
saveLog(`rImap.once ( 'end') before finished test! do imapAccountTest again!`);
1055+
return exports.imapAccountTest(IMapConnect, CallBack);
1056+
}
1057+
return doCallBack(err, null);
10041058
});
10051059
rImap.once('error', err => {
1006-
doCallBack(err, null);
1060+
saveLog(`rImap.once ( 'error' ) [${err.message}]`);
1061+
return doCallBack(err, null);
10071062
});
10081063
};
1009-
const pingPongTimeOut = 1000 * 15;
1064+
const pingPongTimeOut = 1000 * 30;
10101065
class imapPeer extends Event.EventEmitter {
10111066
constructor(imapData, listenBox, writeBox, enCrypto, deCrypto, exit) {
10121067
super();
@@ -1090,12 +1145,15 @@ class imapPeer extends Event.EventEmitter {
10901145
}
10911146
replyPing(uu) {
10921147
return this.enCrypto(JSON.stringify({ pong: uu.ping }), (err, data) => {
1093-
this.trySendToRemote(Buffer.from(data), () => {
1148+
this.trySendToRemote(buffer_1.Buffer.from(data), () => {
10941149
});
10951150
});
10961151
}
10971152
setTimeOutOfPing() {
1153+
saveLog(`setTimeOutOfPing`);
1154+
timers_1.clearTimeout(this.waitingReplyTimeOut);
10981155
return this.waitingReplyTimeOut = timers_1.setTimeout(() => {
1156+
saveLog(`ON setTimeOutOfPing this.emit ( 'pingTimeOut' ) `);
10991157
this.emit('pingTimeOut');
11001158
}, pingPongTimeOut);
11011159
}
@@ -1106,7 +1164,7 @@ class imapPeer extends Event.EventEmitter {
11061164
if (err) {
11071165
return saveLog(`Ping enCrypto error: [${err.message}]`);
11081166
}
1109-
return this.trySendToRemote(Buffer.from(data), () => {
1167+
return this.trySendToRemote(buffer_1.Buffer.from(data), () => {
11101168
return this.setTimeOutOfPing();
11111169
});
11121170
});
@@ -1229,7 +1287,7 @@ class imapPeer extends Event.EventEmitter {
12291287
sendDone() {
12301288
return Async.waterfall([
12311289
next => this.enCrypto(JSON.stringify({ done: new Date().toISOString() }), next),
1232-
(data, next) => this.trySendToRemote(Buffer.from(data), next)
1290+
(data, next) => this.trySendToRemote(buffer_1.Buffer.from(data), next)
12331291
], err => {
12341292
if (err)
12351293
return saveLog(`sendDone got error [${err.message}]`);

0 commit comments

Comments
 (0)