From c0cb5774e9ceb7fdb40b2387217f8b5be70eb315 Mon Sep 17 00:00:00 2001 From: MikalaiR Date: Fri, 25 Mar 2016 16:20:45 +0000 Subject: Telegram: winapi timers git-svn-id: http://svn.miranda-ng.org/main/trunk@16543 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Telegram/src/main.cpp | 20 +++- protocols/Telegram/src/stdafx.h | 18 ++++ protocols/Telegram/src/t_callback.cpp | 4 +- protocols/Telegram/src/t_proto.cpp | 38 +++++-- protocols/Telegram/src/t_proto.h | 4 +- protocols/Telegram/src/t_timers.cpp | 58 ++++++++++ protocols/Telegram/src/t_utils.cpp | 197 +++++++++++++++++++++++++++++++++- 7 files changed, 322 insertions(+), 17 deletions(-) create mode 100644 protocols/Telegram/src/t_timers.cpp (limited to 'protocols/Telegram') diff --git a/protocols/Telegram/src/main.cpp b/protocols/Telegram/src/main.cpp index ca4ccacb51..a186d24ca0 100644 --- a/protocols/Telegram/src/main.cpp +++ b/protocols/Telegram/src/main.cpp @@ -17,10 +17,27 @@ along with this program. If not, see . #include "stdafx.h" +#include +#pragma comment(lib, "delayimp.lib") + +FARPROC WINAPI delayHook(unsigned dliNotify, PDelayLoadInfo dli) +{ + switch (dliNotify) + { + case dliNotePreLoadLibrary: + return (FARPROC)LoadLibraryA(dli->szDll); + } + return NULL; +} + +extern "C" PfnDliHook __pfnDliNotifyHook2 = delayHook; + + int hLangpack; HINSTANCE g_hInstance; CLIST_INTERFACE *pcli; char g_szMirVer[100]; +HANDLE hQueue; PLUGININFOEX pluginInfo = { @@ -54,6 +71,7 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_PROTOC extern "C" int __declspec(dllexport) Load(void) { + hQueue = CreateTimerQueue(); mir_getLP(&pluginInfo); mir_getCLI(); @@ -75,7 +93,7 @@ extern "C" int __declspec(dllexport) Load(void) extern "C" int __declspec(dllexport) Unload(void) { - + DeleteTimerQueue(hQueue); return 0; } diff --git a/protocols/Telegram/src/stdafx.h b/protocols/Telegram/src/stdafx.h index bf44f897c1..2781bcf4f9 100644 --- a/protocols/Telegram/src/stdafx.h +++ b/protocols/Telegram/src/stdafx.h @@ -44,8 +44,26 @@ extern "C" #include "tgl\tgl-net.h" #include "tgl\tgl-timers.h" #include "tgl\tgl-binlog.h" + #include "tgl\config.h" + + struct event; + struct event_base; + event_base __declspec(dllimport) *event_base_new(void); + void *event_get_callback_arg(const void *ev); + struct event *event_new(void *, intptr_t, short, void(*)(intptr_t, short, void *), void *); + int event_del(void *); + int event_add(void *ev, const struct timeval *timeout); +#define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg)) + void event_free(void *); + + + void read_auth_file(struct tgl_state *TLS); + void read_state_file(struct tgl_state *TLS); + void write_auth_file(struct tgl_state *TLS); + void write_state_file(struct tgl_state *TLS); } + struct MirTLS : public tgl_state, public MZeroedObject { struct CTelegramProto *m_proto; diff --git a/protocols/Telegram/src/t_callback.cpp b/protocols/Telegram/src/t_callback.cpp index 9045ab2716..1e097fc1e9 100644 --- a/protocols/Telegram/src/t_callback.cpp +++ b/protocols/Telegram/src/t_callback.cpp @@ -12,7 +12,7 @@ static void user_typing(tgl_state *TLS, tgl_user *U, enum tgl_typing_status stat static void on_login_success(tgl_state *TLS) { - +// write_auth_file(TLS); } static void on_login_failed(tgl_state *TLS) @@ -22,7 +22,7 @@ static void on_login_failed(tgl_state *TLS) static void on_ready(tgl_state *TLS) { - + tgl_do_update_contact_list(TLS, 0, 0); } void request_value(struct tgl_state *TLS, enum tgl_value_type type, const char *prompt, int num_values, diff --git a/protocols/Telegram/src/t_proto.cpp b/protocols/Telegram/src/t_proto.cpp index ee99a0caa9..a54ded0c61 100644 --- a/protocols/Telegram/src/t_proto.cpp +++ b/protocols/Telegram/src/t_proto.cpp @@ -21,15 +21,18 @@ CTelegramProto::CTelegramProto(const char* protoName, const TCHAR* userName) : P { TLS = new MirTLS(this); - tgl_set_verbosity(TLS, 4); + tgl_set_verbosity(TLS, 10); + tgl_set_ev_base(TLS, event_base_new()); + InitNetwork(); InitCallbacks(); - tgl_set_timer_methods(TLS, &tgl_libevent_timers); + extern struct tgl_timer_methods mtgl_libevent_timers; - tgl_set_rsa_key(TLS, "tgl.pub"); + tgl_set_timer_methods(TLS, &mtgl_libevent_timers); + tgl_set_rsa_key(TLS, "tgl.pub"); TLS->base_path = Utils_ReplaceVars("%miranda_profilesdir%\\%miranda_profilename%\\TGL_Data\\"); CreateDirectoryTree(TLS->base_path); @@ -37,20 +40,18 @@ CTelegramProto::CTelegramProto(const char* protoName, const TCHAR* userName) : P tgl_set_download_directory(TLS, CMStringA(FORMAT, "%s\\Downloads\\", TLS->base_path)); CreateDirectoryTree(TLS->downloads_directory); - -// tgl_register_app_id(TLS, TELEGRAM_API_ID, TELEGRAM_API_HASH); -// tgl_set_app_version(TLS, g_szMirVer); + tgl_register_app_id(TLS, TELEGRAM_API_ID, TELEGRAM_API_HASH); + tgl_set_app_version(TLS, g_szMirVer); tgl_init(TLS); - ReadState(); - ReadAuth(); - + bl_do_dc_option(TLS, 1, "", 0, TELEGRAM_API_SERVER, strlen(TELEGRAM_API_SERVER), 443); + bl_do_set_working_dc(TLS, 1); } CTelegramProto::~CTelegramProto() { - SaveState(); + tgl_free_all(TLS); } DWORD_PTR CTelegramProto::GetCaps(int type, MCONTACT) @@ -118,9 +119,15 @@ int CTelegramProto::SendMsg(MCONTACT hContact, int flags, const char *msg) return 0; } +void LoginThread(void* p) +{ + tgl_login(((CTelegramProto*)p)->TLS); +} + int CTelegramProto::SetStatus(int iNewStatus) { - if (iNewStatus == ID_STATUS_ONLINE) tgl_login(TLS); + if (iNewStatus == ID_STATUS_ONLINE) + mir_forkthread(LoginThread, this); return 0; } @@ -147,5 +154,14 @@ void CTelegramProto::TGLGetValue(tgl_value_type type, const char *prompt, int nu { case tgl_phone_number: *result = getStringA("ID"); + if (*result) + break; + default: + ENTER_STRING es = { sizeof(es) }; + es.type = ESF_MULTILINE; + es.caption = mir_a2t(prompt); + EnterString(&es); + *result = mir_t2a(es.ptszResult); + mir_free((void*)es.caption); }; } \ No newline at end of file diff --git a/protocols/Telegram/src/t_proto.h b/protocols/Telegram/src/t_proto.h index fadf3b179c..0e92605487 100644 --- a/protocols/Telegram/src/t_proto.h +++ b/protocols/Telegram/src/t_proto.h @@ -88,10 +88,10 @@ public: void OnUserTyping(tgl_user *U, tgl_typing_status status); - + MirTLS *TLS; private: - MirTLS *TLS; + static mir_cs accountsLock; void ReadState(); diff --git a/protocols/Telegram/src/t_timers.cpp b/protocols/Telegram/src/t_timers.cpp new file mode 100644 index 0000000000..c897247fab --- /dev/null +++ b/protocols/Telegram/src/t_timers.cpp @@ -0,0 +1,58 @@ + +#include "stdafx.h" + +extern HANDLE hQueue; + +struct tgl_timer +{ + tgl_state *TLS; + void(*cb)(struct tgl_state *TLS, void *arg); + void *arg; + HANDLE hTimer; +}; + +VOID CALLBACK WaitOrTimerCallback( + _In_ PVOID lpParameter, + _In_ BOOLEAN TimerOrWaitFired + ) +{ + tgl_timer *p = (tgl_timer*)lpParameter; + p->cb(p->TLS, p->arg); + p->hTimer = 0; +} + + +struct tgl_timer *mtgl_timer_alloc (struct tgl_state *TLS, void (*cb)(struct tgl_state *TLS, void *arg), void *arg) +{ + tgl_timer *p = (tgl_timer *)calloc(sizeof (tgl_timer), 1); + p->TLS = TLS; + p->cb = cb; + p->arg = arg; + return p; +} + +void mtgl_timer_insert (struct tgl_timer *t, double p) +{ + HANDLE hNewTimer = 0; + CreateTimerQueueTimer(&hNewTimer, hQueue, WaitOrTimerCallback, t, (DWORD)(p * 1000), 0, 0); + t->hTimer = hNewTimer; +} + +void mtgl_timer_delete (struct tgl_timer *t) { + DeleteTimerQueueTimer(hQueue, t->hTimer, 0); + t->hTimer = 0; +} + +void mtgl_timer_free (struct tgl_timer *t) +{ + if (t->hTimer) mtgl_timer_delete(t); + free(t); +} + + +struct tgl_timer_methods mtgl_libevent_timers = { + mtgl_timer_alloc, + mtgl_timer_insert, + mtgl_timer_delete, + mtgl_timer_free +}; \ No newline at end of file diff --git a/protocols/Telegram/src/t_utils.cpp b/protocols/Telegram/src/t_utils.cpp index 16d9e1de4c..95a25123ae 100644 --- a/protocols/Telegram/src/t_utils.cpp +++ b/protocols/Telegram/src/t_utils.cpp @@ -1,5 +1,195 @@ #include "stdafx.h" +#include +#include +#include +#include +#include + +#define DC_SERIALIZED_MAGIC 0x868aa81d +#define STATE_FILE_MAGIC 0x28949a93 +#define SECRET_CHAT_FILE_MAGIC 0x37a1988a + + + +void read_state_file(struct tgl_state *TLS) { + CMStringA name(FORMAT, "%sstate", TLS->base_path); + int state_file_fd = open(name, O_CREAT | O_RDWR | O_BINARY, 0600); + + if (state_file_fd < 0) { + return; + } + int version, magic; + if (read(state_file_fd, &magic, 4) < 4) { close(state_file_fd); return; } + if (magic != (int)STATE_FILE_MAGIC) { close(state_file_fd); return; } + if (read(state_file_fd, &version, 4) < 4 || version < 0) { close(state_file_fd); return; } + int x[4]; + if (read(state_file_fd, x, 16) < 16) { + close(state_file_fd); + return; + } + int pts = x[0]; + int qts = x[1]; + int seq = x[2]; + int date = x[3]; + close(state_file_fd); + bl_do_set_seq(TLS, seq); + bl_do_set_pts(TLS, pts); + bl_do_set_qts(TLS, qts); + bl_do_set_date(TLS, date); + TLS->callback.logprintf("read state file: seq=%d pts=%d qts=%d date=%d", seq, pts, qts, date); +} + +void write_state_file(struct tgl_state *TLS) { + int wseq; + int wpts; + int wqts; + int wdate; + wseq = TLS->seq; wpts = TLS->pts; wqts = TLS->qts; wdate = TLS->date; + + CMStringA name(FORMAT, "%sstate", TLS->base_path); + + int state_file_fd = open(name, O_CREAT | O_RDWR | O_BINARY, 0600); + + if (state_file_fd < 0) { + return; + } + int x[6]; + x[0] = STATE_FILE_MAGIC; + x[1] = 0; + x[2] = wpts; + x[3] = wqts; + x[4] = wseq; + x[5] = wdate; + assert(write(state_file_fd, x, 24) == 24); + close(state_file_fd); + TLS->callback.logprintf("wrote state file: wpts=%d wqts=%d wseq=%d wdate=%d", wpts, wqts, wseq, wdate); +} + +void write_dc(struct tgl_dc *DC, void *extra) { + int auth_file_fd = *(int *)extra; + if (!DC) { + int x = 0; + assert(write(auth_file_fd, &x, 4) == 4); + return; + } + else { + int x = 1; + assert(write(auth_file_fd, &x, 4) == 4); + } + + assert(DC->flags & TGLDCF_LOGGED_IN); + + assert(write(auth_file_fd, &DC->options[0]->port, 4) == 4); + int l = strlen(DC->options[0]->ip); + assert(write(auth_file_fd, &l, 4) == 4); + assert(write(auth_file_fd, DC->options[0]->ip, l) == l); + assert(write(auth_file_fd, &DC->auth_key_id, 8) == 8); + assert(write(auth_file_fd, DC->auth_key, 256) == 256); +} + +void write_auth_file(struct tgl_state *TLS) { + CMStringA name(FORMAT, "%sauth", TLS->base_path); + int auth_file_fd = open(name, O_CREAT | O_RDWR | O_BINARY, 0600); + if (auth_file_fd < 0) { return; } + int x = DC_SERIALIZED_MAGIC; + assert(write(auth_file_fd, &x, 4) == 4); + assert(write(auth_file_fd, &TLS->max_dc_num, 4) == 4); + assert(write(auth_file_fd, &TLS->dc_working_num, 4) == 4); + + tgl_dc_iterator_ex(TLS, write_dc, &auth_file_fd); + + assert(write(auth_file_fd, &TLS->our_id, 4) == 4); + close(auth_file_fd); + TLS->callback.logprintf("wrote auth file: magic=%d max_dc_num=%d dc_working_num=%d", x, TLS->max_dc_num, TLS->dc_working_num); +} + +void read_dc(struct tgl_state *TLS, int auth_file_fd, int id, unsigned ver) { + int port = 0; + assert(read(auth_file_fd, &port, 4) == 4); + int l = 0; + assert(read(auth_file_fd, &l, 4) == 4); + assert(l >= 0 && l < 100); + char ip[100]; + assert(read(auth_file_fd, ip, l) == l); + ip[l] = 0; + + long long auth_key_id; + static unsigned char auth_key[256]; + assert(read(auth_file_fd, &auth_key_id, 8) == 8); + assert(read(auth_file_fd, auth_key, 256) == 256); + + bl_do_dc_option(TLS, id, "DC", 2, ip, l, port); + bl_do_set_auth_key(TLS, id, auth_key); + bl_do_dc_signed(TLS, id); + TLS->callback.logprintf("read dc: id=%d", id); +} + +void empty_auth_file(struct tgl_state *TLS) { + TLS->callback.logprintf("initializing empty auth file"); + if (TLS->test_mode) { + bl_do_dc_option(TLS, 1, "", 0, TG_SERVER_TEST_1, strlen(TG_SERVER_TEST_1), 443); + bl_do_dc_option(TLS, 2, "", 0, TG_SERVER_TEST_2, strlen(TG_SERVER_TEST_2), 443); + bl_do_dc_option(TLS, 3, "", 0, TG_SERVER_TEST_3, strlen(TG_SERVER_TEST_3), 443); + bl_do_set_working_dc(TLS, TG_SERVER_TEST_DEFAULT); + } + else { + bl_do_dc_option(TLS, 1, "", 0, TG_SERVER_1, strlen(TG_SERVER_1), 443); + bl_do_dc_option(TLS, 2, "", 0, TG_SERVER_2, strlen(TG_SERVER_2), 443); + bl_do_dc_option(TLS, 3, "", 0, TG_SERVER_3, strlen(TG_SERVER_3), 443); + bl_do_dc_option(TLS, 4, "", 0, TG_SERVER_4, strlen(TG_SERVER_4), 443); + bl_do_dc_option(TLS, 5, "", 0, TG_SERVER_5, strlen(TG_SERVER_5), 443); + bl_do_set_working_dc(TLS, TG_SERVER_DEFAULT); + } +} + +void read_auth_file(struct tgl_state *TLS) { + CMStringA name(FORMAT, "%sauth", TLS->base_path); + int auth_file_fd = open(name, O_CREAT | O_RDWR | O_BINARY, 0600); + if (auth_file_fd < 0) { + empty_auth_file(TLS); + return; + } + assert(auth_file_fd >= 0); + unsigned x; + unsigned m; + if (read(auth_file_fd, &m, 4) < 4 || (m != DC_SERIALIZED_MAGIC)) { + close(auth_file_fd); + empty_auth_file(TLS); + return; + } + assert(read(auth_file_fd, &x, 4) == 4); + assert(x > 0); + int dc_working_num; + assert(read(auth_file_fd, &dc_working_num, 4) == 4); + + int i; + for (i = 0; i <= (int)x; i++) { + int y; + assert(read(auth_file_fd, &y, 4) == 4); + if (y) { + read_dc(TLS, auth_file_fd, i, m); + } + } + bl_do_set_working_dc(TLS, dc_working_num); + int our_id; + int l = read(auth_file_fd, &our_id, 4); + if (l < 4) { + assert(!l); + } + if (our_id) { + bl_do_set_our_id(TLS, our_id); + } + close(auth_file_fd); + TLS->callback.logprintf("read auth file: dcs=%d dc_working_num=%d our_id=%d", x, dc_working_num, our_id); +} + + + + + + + void CTelegramProto::ReadState() { DBVARIANT dbv = { 0 }; @@ -87,4 +277,9 @@ void CTelegramProto::ReadAuth() } db_free(&dbv); -} \ No newline at end of file +} + + +void CTelegramProto::SaveAuth() +{ +} -- cgit v1.2.3