00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#pragma warning(disable:4786)
00023 #define _WIN32_WINNT 0x0400
00024 #define _WIN32_IE 0x0500
00025
00026
#include <windows.h>
00027
00028
#include <ListenSocket.h>
00029
#include <config-win.h>
00030
#include <mysql.h>
00031
#include <libmysqlwrapped.h>
00032
#include <stdio.h>
00033
#include <shellapi.h>
00034
#include "resource.h"
00035
#include <socket_include.h>
00036
#include <SocketHandler.h>
00037
#include <HttpGetSocket.h>
00038
#include <process.h>
00039
#include <commctrl.h>
00040
#include <StdoutLog.h>
00041
#include "Mutex.h"
00042
#include "MyErrlog.h"
00043
#include "MySocketsLog.h"
00044
#include "MenuHandler.h"
00045
#include "MyMenu.h"
00046
#include <Utility.h>
00047
#include <libcgi++.h>
00048
#include "FinderHandler.h"
00049
#include "ExecSocket.h"
00050
#include "MyMinionSocket.h"
00051
#include "MyMinderSocket.h"
00052
00053
#include "MyApp.h"
00054
00055
00056
00057
00058 static HANDLE
g_hD2;
00059
00060 #define D2(x) { \
00061
Mutex lock(g_hD2); \
00062
if (lock.Locked()) \
00063
{ \
00064
FILE *fil = fopen("c:\\deb.log","at"); \
00065
x; \
00066
fclose(fil); \
00067
} \
00068
}
00069
00070
00071
00072 static bool g_bQuit =
false;
00073 static HANDLE
g_hMutex;
00074 static bool g_bRestart =
true;
00075 static HANDLE
g_hMutexScan;
00076 static bool g_bWsRunning =
false;
00077 static MenuHandler g_menuHandler;
00078
00079
00080 MyApp *
g_app = NULL;
00081 HWND
g_hwndMain;
00082
00083
00084 MyApp::MyApp(HINSTANCE hInst,HINSTANCE hPrevInst,Database& db) :
WinApp(hInst, hPrevInst)
00085 ,m_db(db)
00086 ,m_quit(false)
00087 ,m_local_port(18018)
00088 ,m_bind_local(true)
00089 ,m_minder_host("localhost")
00090 ,m_minder_port(9696)
00091 ,m_minion_port(19696)
00092 ,m_no_minder(true)
00093 ,m_new_minder_host(m_minder_host)
00094 ,m_new_minder_port(m_minder_port)
00095 ,m_new_no_minder(m_no_minder)
00096 ,m_create_top(false)
00097 ,m_join_group("fd")
00098 ,m_use_password(true)
00099 ,m_new_join_group(m_join_group)
00100 ,m_new_use_password(m_use_password)
00101 {
00102
g_app =
this;
00103 }
00104
00105
00106 MyApp::~MyApp()
00107 {
00108 }
00109
00110
00111
00112 DWORD WINAPI
start( LPVOID lpParam )
00113 {
00114 mysql_thread_init();
00115
MyErrlog log;
00116
g_bWsRunning =
true;
00117 {
00118 Database db(
"fd",&log);
00119
while (
g_bRestart)
00120 {
00121
MySocketsLog log;
00122
FinderHandler h(db);
00123 h.RegStdLog(&log);
00124 h.ResolveLocal();
00125 ListenSocket<ExecSocket> l(h);
00126 ListenSocket<MyMinionSocket> l2(h);
00127
00128
g_app->
ApplyChanges();
00129
00130 std::string address =
g_app->
BindLocal() ?
"127.0.0.1" :
"0.0.0.0";
00131 l.Bind(address,
g_app->
GetLocalPort());
00132 h.Add(&l);
00133
if (!
g_app->
NoMinder())
00134 {
00135
int port =
g_app->
GetMinionPort();
00136
while (l2.Bind( port ))
00137 {
00138 port++;
00139 }
00140 h.Add(&l2);
00141 h.SetLocalPort( port );
00142
g_app->
reg_minder(h,
"Hello");
00143 }
00144
00145 time_t tminder = time(NULL);
00146 time_t tminion = time(NULL) - 30;
00147 time_t ttop = time(NULL);
00148
00149 h.Select(1,0);
00150
00151
g_bRestart =
false;
00152
while (h.GetCount() && !
g_bQuit && !
g_bRestart)
00153 {
00154 h.Select(1,0);
00155 time_t tnow = time(NULL);
00156
if (!
g_app->
NoMinder())
00157 {
00158
if (tnow - tminder > 15 * 60 )
00159 {
00160
g_app->
reg_minder(h,
"Hello");
00161 tminder = tnow;
00162 }
00163
if (tnow - tminion > 60 )
00164 {
00165
g_app->
minion_connect(h);
00166 tminion = tnow;
00167 }
00168
if (
g_app->
CreateTop())
00169 {
00170
if (ttop < tnow)
00171 {
00172 h.
BeginTop();
00173 ttop = tnow + 15;
00174 }
00175
else
00176
if (ttop == tnow)
00177 {
00178 h.
EndTop();
00179
g_app->
SetCreateTop(
false );
00180 }
00181 }
00182 }
00183 }
00184
if (!
g_app->
NoMinder())
00185 {
00186
g_app->
reg_minder(h,
"Goodbye");
00187 h.Select(1,0);
00188
while (h.MinderSockets())
00189 {
00190 h.Select(1,0);
00191 }
00192 }
00193 }
00194 }
00195
00196
g_bWsRunning =
false;
00197 mysql_thread_end();
00198
return 0;
00199 }
00200
00201
00202 static int CALLBACK
MyDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00203 {
00204
switch (uMsg)
00205 {
00206
case WM_INITDIALOG:
00207
break;
00208
00209
case WM_SHELLNOTIFY:
00210
if (lParam == WM_LBUTTONDBLCLK)
00211 {
00212
char cmd[100];
00213 sprintf(cmd,
"http://127.0.0.1:%d/",
g_app->
GetLocalPort());
00214 ::ShellExecute(NULL, NULL, cmd, NULL,
"", SW_SHOW);
00215 }
00216
else
00217
if (lParam == WM_RBUTTONDOWN)
00218 {
00219
MyMenu m(
g_menuHandler);
00220 POINT pt;
00221
00222 GetCursorPos(&pt);
00223 SetForegroundWindow(
g_hwndMain);
00224
int cmd = TrackPopupMenuEx(m.
Handle(),
00225 TPM_RIGHTALIGN|TPM_BOTTOMALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD,
00226 pt.x, pt.y,
g_hwndMain, NULL);
00227
if (cmd)
00228 {
00229
if (!
g_menuHandler.
OnCommand( cmd ))
00230 {
00231 ::PostMessage(
g_hwndMain, WM_COMMAND, cmd, 0);
00232 }
00233 }
00234 ::PostMessage(
g_hwndMain, WM_NULL, 0, 0);
00235 }
00236
break;
00237
case WM_INITMENU:
00238
D2(fprintf(fil,
"WM_INITMENU %08lx %08lx\n",wParam,lParam);)
00239 {
00240 HMENU hMenu = (HMENU)wParam;
00241
g_menuHandler.
OnInitMenu(hMenu);
00242 }
00243
break;
00244
case WM_INITMENUPOPUP:
00245
D2(fprintf(fil,
"WM_INITMENUPOPUP %08lx %08lx\n",wParam,lParam);)
00246 {
00247 HMENU hMenu = (HMENU)wParam;
00248
int relpos = lParam & 0xffff;
00249
int winmenu = (lParam >> 16) & 0xffff;
00250
D2(fprintf(fil,
" relpos: %d winmenu: %d\n",relpos,winmenu););
00251 {
00252 MENUITEMINFO info;
00253 ::GetMenuItemInfo(hMenu, relpos,
true, &info);
00254 }
00255
g_menuHandler.
OnInitPopupMenu(hMenu, relpos, winmenu ?
true :
false);
00256 }
00257
break;
00258
case WM_MENUSELECT:
00259
D2(fprintf(fil,
"WM_MENUSELECT %08lx %08lx\n",wParam,lParam);)
00260 {
00261 HMENU hMenu = (HMENU)lParam;
00262
int index = wParam & 0xffff;
00263
int flags = (wParam >> 16) & 0xffff;
00264
g_menuHandler.
OnMenuSelect(hMenu, index, flags);
00265 }
00266
break;
00267
00268
case WM_CHANGE_ICON:
00269
g_app->
ChangeIcon( wParam );
00270
break;
00271
case WM_COMMAND:
00272
switch (wParam)
00273 {
00274
case IDOK:
00275
g_app->
GetDialogData();
00276
case IDCANCEL:
00277 ShowWindow(
g_hwndMain, SW_HIDE);
00278
break;
00279
case ID_POPUP_EXIT:
00280
g_app->
SetQuit();
00281
break;
00282
00283
default:
00284
break;
00285 }
00286
break;
00287 }
00288
return 0;
00289 }
00290
00291
00292 void MyApp::ApplyChanges()
00293 {
00294
m_minder_host =
m_new_minder_host;
00295
m_minder_port =
m_new_minder_port;
00296
m_no_minder =
m_new_no_minder;
00297
m_join_group =
m_new_join_group;
00298
m_use_password =
m_new_use_password;
00299
m_group_password =
m_new_group_password;
00300
00301
if (
m_no_minder)
00302 {
00303 ::PostMessage(
g_hwndMain,
WM_CHANGE_ICON,
IDR_MAIN, 0);
00304 }
00305
else
00306 {
00307 ::PostMessage(
g_hwndMain,
WM_CHANGE_ICON,
IDI_GREY, 0);
00308 }
00309 }
00310
00311
00312 void MyApp::SetDialogData()
00313 {
00314
if (IsWindow(
g_hwndMain))
00315 {
00316
char slask[1000];
00317
00318 sprintf(slask,
"%d",
m_local_port);
00319 SetWindowText(GetDlgItem(
g_hwndMain,
IDED_LOCAL_PORT), slask);
00320
00321 ::CheckDlgButton(
g_hwndMain,
IDRB_BIND_LOCAL,
m_bind_local ? 0 : 1);
00322
00323 SetWindowText(GetDlgItem(
g_hwndMain,
IDED_MINDER_HOST),
m_minder_host.c_str());
00324
00325 sprintf(slask,
"%d",
m_minder_port);
00326 SetWindowText(GetDlgItem(
g_hwndMain,
IDED_MINDER_PORT), slask);
00327
00328 sprintf(slask,
"%d",
m_minion_port);
00329 SetWindowText(GetDlgItem(
g_hwndMain,
IDED_MINION_PORT), slask);
00330
00331 ::CheckDlgButton(
g_hwndMain,
IDRB_NO_MINDER,
m_no_minder ? 0 : 1);
00332
00333 SetWindowText(GetDlgItem(
g_hwndMain,
IDED_JOIN_GROUP),
m_join_group.c_str());
00334 SetWindowText(GetDlgItem(
g_hwndMain,
IDED_GROUP_PASSWORD),
m_group_password.c_str());
00335 }
00336 }
00337
00338
00339 void MyApp::GetDialogData()
00340 {
00341
if (IsWindow(
g_hwndMain))
00342 {
00343
int old_local_port =
m_local_port;
00344
bool old_bind_local =
m_bind_local;
00345
char slask[1000];
00346
00347 GetWindowText(GetDlgItem(
g_hwndMain,
IDED_LOCAL_PORT), (LPSTR)slask, 1000);
00348 m_local_port = atoi(slask);
00349
00350 m_bind_local = ::IsDlgButtonChecked(
g_hwndMain,
IDRB_BIND_LOCAL) ?
false :
true;
00351
00352 GetWindowText(GetDlgItem(
g_hwndMain,
IDED_MINDER_HOST), (LPSTR)slask, 1000);
00353
m_new_minder_host = slask;
00354
00355 GetWindowText(GetDlgItem(
g_hwndMain,
IDED_MINDER_PORT), (LPSTR)slask, 1000);
00356
m_new_minder_port = atoi(slask);
00357
00358
m_new_no_minder = ::IsDlgButtonChecked(
g_hwndMain,
IDRB_NO_MINDER) ?
false :
true;
00359
00360
m_create_top = ::IsDlgButtonChecked(
g_hwndMain,
IDRB_CREATE_TOP) ?
true :
false;
00361
00362 GetWindowText(GetDlgItem(
g_hwndMain,
IDED_JOIN_GROUP), (LPSTR)slask, 1000);
00363
m_new_join_group = slask;
00364 GetWindowText(GetDlgItem(
g_hwndMain,
IDED_GROUP_PASSWORD), (LPSTR)slask, 1000);
00365
m_new_group_password = slask;
00366
00367
if (m_local_port != old_local_port ||
00368 m_bind_local != old_bind_local ||
00369
m_new_minder_host !=
m_minder_host ||
00370
m_new_minder_port !=
m_minder_port ||
00371
m_new_no_minder !=
m_no_minder ||
00372
m_new_join_group !=
m_join_group ||
00373
m_new_group_password !=
m_group_password
00374 )
00375 {
00376
g_bRestart =
true;
00377 }
00378 }
00379 }
00380
00381
00382 void MyApp::ShowTaskBar(BOOL show)
00383 {
00384 NOTIFYICONDATA tnid;
00385 DWORD dwMsg;
00386
00387 tnid.cbSize =
sizeof(NOTIFYICONDATA);
00388 tnid.hWnd =
g_hwndMain;
00389
00390
if (show)
00391 {
00392 tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
00393 tnid.uCallbackMessage =
WM_SHELLNOTIFY;
00394 tnid.hIcon = (HICON)LoadImage(
GetInstance(), MAKEINTRESOURCE(
IDR_MAIN), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
00395 tnid.uID =
IDR_MAIN;
00396
00397 strcpy(tnid.szTip,
"fd");
00398 dwMsg = NIM_ADD;
00399 }
00400
else
00401 {
00402 tnid.uFlags = 0;
00403 tnid.uID =
IDR_MAIN;
00404 dwMsg = NIM_DELETE;
00405 }
00406
00407 ::Shell_NotifyIcon(dwMsg, &tnid);
00408 }
00409
00410
00411 int MyApp::Init(LPSTR lpCmdLine,
int nCmdShow)
00412 {
00413
if (!(
g_hwndMain = CreateDialog(
GetInstance(), MAKEINTRESOURCE(
IDD_SETTINGS), GetDesktopWindow(),
MyDlgProc)))
00414 {
00415 ::MessageBox(GetDesktopWindow(),
"Unable to create dialog",
"Error", MB_OK);
00416
return -1;
00417 }
00418
00419
00420
g_hMutex = ::CreateMutex(NULL, FALSE, NULL);
00421
g_hMutexScan = ::CreateMutex(NULL, FALSE, NULL);
00422
g_hD2 = ::CreateMutex(NULL, FALSE, NULL);
00423
00424
00425 SendMessage(
g_hwndMain, WM_SETICON, TRUE, (LPARAM)LoadIcon(
GetInstance(), MAKEINTRESOURCE(
IDR_MAIN)));
00426
ShowTaskBar(
true);
00427
00428
00429 HANDLE h;
00430 DWORD dwThreadId;
00431 h = CreateThread(NULL, 0,
start, NULL, 0, &dwThreadId);
00432
00433
00434 {
00435 MSG msg;
00436
while (!
m_quit && IsWindow(
g_hwndMain) && GetMessage(&msg,
g_hwndMain, NULL, NULL) != WM_QUIT)
00437 {
00438
if (!IsDialogMessage(
g_hwndMain, &msg))
00439 {
00440 DispatchMessage(&msg);
00441 }
00442 }
00443 }
00444
D2(fprintf(fil,
"shutting down\n");)
00445
00446
00447
g_bQuit =
true;
00448
00449
00450 {
00451 ShowWindow(
g_hwndMain, SW_HIDE);
00452
D2(fprintf(fil,
"hide window\n");)
00453
00454
00455
bool bWait =
true;
00456
int timeout = 50;
00457
while (bWait && timeout--)
00458 {
00459 Sleep(100);
00460 bWait =
false;
00461
if (
g_bWsRunning)
00462 {
00463 bWait =
true;
00464 }
00465 }
00466
if (!timeout)
00467 {
00468 ::MessageBox(NULL,
"Thread wait timeout",
"", MB_OK);
00469 }
00470
#ifdef _DEBUG
00471
::MessageBox(NULL,
"All threads gone",
"", MB_OK);
00472
#endif
00473
00474 CloseHandle(h);
00475
D2(fprintf(fil,
"webserver h closed\n");)
00476
00477 DestroyWindow(
g_hwndMain);
00478
D2(fprintf(fil,
"g_hwndMain closed\n");)
00479 }
00480
00481
ShowTaskBar(
false);
00482
D2(fprintf(fil,
"taskbar icon removed\n");)
00483 ::CloseHandle(
g_hMutex);
00484
D2(fprintf(fil,
"g_hMutex closed\n");)
00485 ::CloseHandle(
g_hMutexScan);
00486
D2(fprintf(fil,
"g_hMutexScan closed\n");)
00487 ::CloseHandle(
g_hD2);
00488
00489
00490
D2(fprintf(fil,
"MyApp::Init() returns 0\n");)
00491
return 0;
00492 }
00493
00494
00495 int MyApp::MemoryUsage()
00496 {
00497
typedef BOOL (_stdcall * GetProcessMemoryInfoPtr)(HANDLE,
void*, DWORD);
00498
struct _PROCESS_MEMORY_COUNTERS
00499 {
00500 DWORD cb;
00501 DWORD PageFaultCount;
00502 SIZE_T PeakWorkingSetSize;
00503 SIZE_T WorkingSetSize;
00504 SIZE_T QuotaPeakPagedPoolUsage;
00505 SIZE_T QuotaPagedPoolUsage;
00506 SIZE_T QuotaPeakNonPagedPoolUsage;
00507 SIZE_T QuotaNonPagedPoolUsage;
00508 SIZE_T PagefileUsage;
00509 SIZE_T PeakPagefileUsage;
00510 };
00511
00512 HINSTANCE hLib;
00513 GetProcessMemoryInfoPtr GetProcessMemoryInfo;
00514
struct _PROCESS_MEMORY_COUNTERS mem;
00515
int result = 0;
00516
00517 memset(&mem, 0,
sizeof(mem));
00518 mem.cb =
sizeof(mem);
00519
if ((hLib = LoadLibrary(
"psapi.dll")) != NULL)
00520 {
00521
if ((GetProcessMemoryInfo = (GetProcessMemoryInfoPtr)GetProcAddress(hLib,
"GetProcessMemoryInfo")) != NULL)
00522 {
00523
if ((*GetProcessMemoryInfo)(GetCurrentProcess(), &mem,
sizeof(mem)))
00524 {
00525 result = mem.WorkingSetSize / 1024;
00526 }
00527 }
00528 FreeLibrary(hLib);
00529 }
00530
return result;
00531 }
00532
00533
00534 BOOL
MyApp::ShowBalloonTip(
const std::string& title,
const std::string& msg)
00535 {
00536 NOTIFYICONDATA tnid;
00537 DWORD uTimeout = 500;
00538 memset(&tnid, 0,
sizeof(tnid));
00539 tnid.cbSize =
sizeof(NOTIFYICONDATA);
00540 tnid.hWnd =
g_hwndMain;
00541 tnid.uID =
IDR_MAIN;
00542 tnid.uFlags = NIF_INFO;
00543 tnid.uTimeout = uTimeout;
00544 tnid.dwInfoFlags = NIIF_INFO;
00545
00546
00547
00548
00549
00550
00551 strcpy(tnid.szInfo, msg.c_str() );
00552 strcpy(tnid.szInfoTitle, title.c_str() );
00553
return Shell_NotifyIcon(NIM_MODIFY, &tnid);
00554 }
00555
00556
00557 void MyApp::ChangeIcon(
int id)
00558 {
00559 NOTIFYICONDATA tnid;
00560 DWORD uTimeout = 500;
00561 memset(&tnid, 0,
sizeof(tnid));
00562 tnid.cbSize =
sizeof(NOTIFYICONDATA);
00563 tnid.hWnd =
g_hwndMain;
00564 tnid.uID =
IDR_MAIN;
00565 tnid.uFlags = NIF_ICON;
00566 tnid.hIcon = (HICON)LoadImage(
GetInstance(), MAKEINTRESOURCE(
id), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
00567 Shell_NotifyIcon(NIM_MODIFY, &tnid);
00568 }
00569
00570
00571 void MyApp::reg_minder(
FinderHandler& h,
const std::string& cmd)
00572 {
00573 std::string group = Utility::base64(
m_join_group);
00574
if (
m_use_password &&
m_group_password.size())
00575 {
00576 group +=
"/" + Utility::base64(
m_group_password);
00577 }
00578
MyMinderSocket *m =
new MyMinderSocket(h, group);
00579 m ->
Init();
00580
00581 ::PostMessage(
g_hwndMain,
WM_CHANGE_ICON,
IDI_YELLOW, 0);
00582 m -> Function(cmd);
00583 m -> SetDeleteByHandler(
true);
00584
bool opened = m -> Open(
m_minder_host.c_str(),
m_minder_port);
00585 h.Add(m);
00586 m -> SetLocalIpPort(h.GetLocalAddress(),h.GetLocalPort());
00587
if (opened && !m -> Connecting())
00588 {
00589 m -> SendHello();
00590 }
00591
if (!opened && !m->Connecting())
00592 {
00593 ::PostMessage(
g_hwndMain,
WM_CHANGE_ICON,
IDI_RED, 0);
00594 m->SetCloseAndDelete();
00595 }
00596
00597 }
00598
00599
00600 void MyApp::minion_connect(
FinderHandler& h)
00601 {
00602
if (h.Count() < 3)
00603 {
00604 ipaddr_t a;
00605 port_t p;
00606 std::string key;
00607
long host_id;
00608
if (h.GetHost(a,p,key,host_id))
00609 {
00610 MinionSocket *tmp =
new MyMinionSocket(h,key,a,p);
00611 tmp ->
Init();
00612 ipaddr_t my_ip;
00613 port_t my_port;
00614 h.GetMyIpPort(my_ip, my_port);
00615 tmp -> SetMyIpPort(my_ip,my_port);
00616 tmp -> SetRemoteHostId(host_id);
00617
if (tmp -> Open(a,p))
00618 {
00619 tmp -> SetDeleteByHandler(
true);
00620 h.Add(tmp);
00621
00622 tmp -> SendHello(
"Hello");
00623 }
00624
else
00625
if (tmp -> Connecting())
00626 {
00627 tmp -> SetDeleteByHandler(
true);
00628
00629 h.Add(tmp);
00630 }
00631
else
00632 {
00633
delete tmp;
00634 }
00635 }
00636
else
00637 {
00638 h.LogError(NULL,
"minion_connect", 0,
"GetHost() failed");
00639 }
00640 }
00641 }
00642
00643