win32: use #ifdef _WIN32
[olsrd.git] / gui / win32 / Main / FrontendDlg.cpp
1 /*
2  * The olsr.org Optimized Link-State Routing daemon (olsrd)
3  * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  */
40
41 #ifdef _WIN32
42
43 #include "stdafx.h"
44 #include "Frontend.h"
45 #include "FrontendDlg.h"
46 #include "TrayIcon.h"
47
48 #include "Ipc.h"
49
50 #ifdef _DEBUG
51 #define new DEBUG_NEW
52 #undef THIS_FILE
53 static char THIS_FILE[] = __FILE__;
54 #endif /* _DEBUG */
55
56 CFrontendDlg::CFrontendDlg(CWnd* pParent)
57         : CDialog(CFrontendDlg::IDD, pParent)
58 {
59         //{{AFX_DATA_INIT(CFrontendDlg)
60         //}}AFX_DATA_INIT
61
62         Event = CreateEvent(NULL, FALSE, FALSE, "TheOlsrdShimEvent");
63
64         LogThread = NULL;
65         NetThread = NULL;
66 }
67
68 void CFrontendDlg::DoDataExchange(CDataExchange* pDX)
69 {
70         CDialog::DoDataExchange(pDX);
71         //{{AFX_DATA_MAP(CFrontendDlg)
72         DDX_Control(pDX, IDC_BUTTON2, m_StopButton);
73         DDX_Control(pDX, IDC_BUTTON1, m_StartButton);
74         DDX_Control(pDX, IDC_TAB1, m_TabCtrl);
75         //}}AFX_DATA_MAP
76 }
77
78 BEGIN_MESSAGE_MAP(CFrontendDlg, CDialog)
79         //{{AFX_MSG_MAP(CFrontendDlg)
80         ON_BN_CLICKED(IDC_BUTTON1, OnStartButton)
81         ON_BN_CLICKED(IDC_BUTTON2, OnStopButton)
82         ON_BN_CLICKED(IDC_BUTTON3, OnExitButton)
83         ON_BN_CLICKED(IDOK, OnOK)
84         ON_BN_CLICKED(IDCANCEL, OnCancel)
85         //}}AFX_MSG_MAP
86 END_MESSAGE_MAP()
87
88 #if 0
89 static void HexDump(unsigned char *Mem, int Len)
90 {
91         char Buff[10000];
92         int i, k;
93         char *Walker = Buff;
94
95         for (i = 0; i < Len; i += k)
96         {
97                 Walker += sprintf(Walker, "%08x:", i);
98
99                 for (k = 0; i + k < Len && k < 16; k++)
100                         Walker += sprintf(Walker, " %02x", Mem[i + k]);
101
102                 while (k < 16)
103                 {
104                         Walker += sprintf(Walker, "   ");
105                         k++;
106                 }
107
108                 Walker += sprintf(Walker, " ");
109
110                 for (k = 0; i + k < Len && k < 16; k++)
111                         if (Mem[i + k] < 32 || Mem[i + k] > 126)
112                                 Walker += sprintf(Walker, ".");
113
114                         else
115                                 Walker += sprintf(Walker, "%c", Mem[i + k]);
116
117                 Walker += sprintf(Walker, "\r\n");
118         }
119
120         ::MessageBox(NULL, Buff, "HEXDUMP", MB_OK);
121 }
122 #endif
123
124 // XXX - pretty inefficient
125
126 void CFrontendDlg::Timeout(void)
127 {
128         POSITION Pos, Pos2;
129         class NodeEntry Entry;
130         class MprEntry MprEntry;
131         class MidEntry MidEntry;
132         class HnaEntry HnaEntry;
133
134 Restart0:
135         Pos = NodeList.GetHeadPosition();
136
137         while (Pos != NULL)
138         {
139                 Entry = NodeList.GetAt(Pos);
140
141                 if (Entry.Timeout < Now)
142                 {
143                         NodeList.RemoveAt(Pos);
144                         goto Restart0;
145                 }
146
147 Restart1:
148                 Pos2 = Entry.MprList.GetHeadPosition();
149
150                 while (Pos2 != NULL)
151                 {
152                         MprEntry = Entry.MprList.GetAt(Pos2);
153
154                         if (MprEntry.Timeout < Now)
155                         {
156                                 Entry.MprList.RemoveAt(Pos2);
157                                 goto Restart1;
158                         }
159
160                         Entry.MprList.GetNext(Pos2);
161                 }
162
163 Restart2:
164                 Pos2 = Entry.MidList.GetHeadPosition();
165
166                 while (Pos2 != NULL)
167                 {
168                         MidEntry = Entry.MidList.GetAt(Pos2);
169
170                         if (MidEntry.Timeout < Now)
171                         {
172                                 Entry.MidList.RemoveAt(Pos2);
173                                 goto Restart2;
174                         }
175
176                         Entry.MidList.GetNext(Pos2);
177                 }
178
179 Restart3:
180                 Pos2 = Entry.HnaList.GetHeadPosition();
181
182                 while (Pos2 != NULL)
183                 {
184                         HnaEntry = Entry.HnaList.GetAt(Pos2);
185
186                         if (HnaEntry.Timeout < Now)
187                         {
188                                 Entry.HnaList.RemoveAt(Pos2);
189                                 goto Restart3;
190                         }
191
192                         Entry.HnaList.GetNext(Pos2);
193                 }
194
195                 NodeList.GetNext(Pos);
196         }
197
198         if( NodeList.IsEmpty() )
199                 TrayIcon::getInstance()->setStatus( TrayIcon::ON, "No nodes found" );
200         else
201                 TrayIcon::getInstance()->setStatus( TrayIcon::CONNECTED, "Nodes available" );
202
203         m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
204 }
205
206 unsigned int VTimeToInt(unsigned int VTime)
207 {
208         return ((0x10 | ((VTime & 0xf0) >> 4)) << (VTime & 0x0f)) >> 8;
209 }
210
211 void CFrontendDlg::AddMpr(unsigned int MprAddr, unsigned int NodeAddr,
212                                                   unsigned int VTime)
213 {
214         class NodeEntry NewEntry;
215         POSITION Pos;
216         unsigned __int64 Timeout;
217
218         Timeout = Now +
219                 (unsigned __int64)VTimeToInt(VTime) * (unsigned __int64)10000000;
220
221         AddNode(NodeAddr, VTime);
222         AddNode(MprAddr, VTime);
223
224         NewEntry.Addr = NodeAddr;
225
226         Pos = NodeList.Find(NewEntry);
227
228         if (Pos == NULL)
229                 return;
230
231         class NodeEntry &OldEntry = NodeList.GetAt(Pos);
232
233         OldEntry.AddMpr(MprAddr, Timeout);
234
235         m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
236 }
237
238 void CFrontendDlg::AddMid(unsigned int IntAddr, unsigned int NodeAddr,
239                                                   unsigned int VTime)
240 {
241         class NodeEntry NewEntry;
242         POSITION Pos;
243         unsigned __int64 Timeout;
244
245         Timeout = Now +
246                 (unsigned __int64)VTimeToInt(VTime) * (unsigned __int64)10000000;
247
248         AddNode(NodeAddr, VTime);
249
250         NewEntry.Addr = NodeAddr;
251
252         Pos = NodeList.Find(NewEntry);
253
254         if (Pos == NULL)
255                 return;
256
257         class NodeEntry &OldEntry = NodeList.GetAt(Pos);
258
259         OldEntry.AddMid(IntAddr, Timeout);
260
261         m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
262 }
263
264 void CFrontendDlg::AddHna(unsigned int NetAddr, unsigned int NetMask,
265                                                   unsigned int NodeAddr, unsigned int VTime)
266 {
267         class NodeEntry NewEntry;
268         POSITION Pos;
269         unsigned __int64 Timeout;
270
271         Timeout = Now +
272                 (unsigned __int64)VTimeToInt(VTime) * (unsigned __int64)10000000;
273
274         AddNode(NodeAddr, VTime);
275
276         NewEntry.Addr = NodeAddr;
277
278         Pos = NodeList.Find(NewEntry);
279
280         if (Pos == NULL)
281                 return;
282
283         class NodeEntry &OldEntry = NodeList.GetAt(Pos);
284
285         OldEntry.AddHna(NetAddr, NetMask, Timeout);
286
287         m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
288 }
289
290 void CFrontendDlg::AddNode(unsigned int NodeAddr, unsigned int VTime)
291 {
292         class NodeEntry NewEntry;
293         POSITION Pos;
294         unsigned __int64 Timeout;
295
296         if (NodeAddr == LocalHost)
297                 return;
298
299         Timeout = Now +
300                 (unsigned __int64)VTimeToInt(VTime) * (unsigned __int64)10000000;
301
302         NewEntry.Addr = NodeAddr;
303
304         Pos = NodeList.Find(NewEntry);
305
306         if (Pos != NULL)
307         {
308                 class NodeEntry &OldEntry = NodeList.GetAt(Pos);
309                 OldEntry.Timeout = Timeout;
310         }
311
312         else
313         {
314                 NewEntry.Timeout = Timeout;
315                 NodeList.AddTail(NewEntry);
316         }
317
318         m_TabCtrl.m_Dialog3.UpdateNodeInfo(NodeList);
319 }
320
321 void CFrontendDlg::HandleOlsrTc(struct OlsrTc *Msg, int UseLq)
322 {
323         int Size;
324         unsigned int *Addr;
325
326         Msg->Header.SeqNo = ::ntohs(Msg->Header.SeqNo);
327         Msg->Ansn = ::ntohs(Msg->Ansn);
328
329         AddNode(Msg->Header.Orig, Msg->Header.VTime);
330
331         Size = Msg->Header.Size;
332
333         Size -= sizeof (struct OlsrTc);
334
335         Addr = (unsigned int *)(Msg + 1);
336
337         while (Size > 0)
338         {
339                 Size -= 4;
340
341                 AddMpr(*Addr, Msg->Header.Orig, Msg->Header.VTime);
342
343                 Addr++;
344
345                 if (UseLq != 0)
346                 {
347                         Size -= 4;
348                         Addr++;
349                 }
350
351         }
352 }
353
354 void CFrontendDlg::HandleOlsrMid(struct OlsrHeader *Msg)
355 {
356         int Size;
357         unsigned int *Addr;
358
359         Msg->SeqNo = ::ntohs(Msg->SeqNo);
360
361         AddNode(Msg->Orig, Msg->VTime);
362
363         Size = Msg->Size;
364
365         Size -= sizeof (struct OlsrHeader);
366
367         Addr = (unsigned int *)(Msg + 1);
368
369         while (Size > 0)
370         {
371                 Size -= 4;
372
373                 AddMid(*Addr, Msg->Orig, Msg->VTime);
374
375                 Addr++;
376         }
377 }
378
379 void CFrontendDlg::HandleOlsrHna(struct OlsrHeader *Msg)
380 {
381         int Size;
382         unsigned int *Addr;
383
384         Msg->SeqNo = ::ntohs(Msg->SeqNo);
385
386         AddNode(Msg->Orig, Msg->VTime);
387
388         Size = Msg->Size;
389
390         Size -= sizeof (struct OlsrHeader);
391
392         Addr = (unsigned int *)(Msg + 1);
393
394         while (Size > 0)
395         {
396                 Size -= 8;
397
398                 AddHna(Addr[0], Addr[1], Msg->Orig, Msg->VTime);
399
400                 Addr += 2;
401         }
402 }
403
404 void CFrontendDlg::HandleOlsrHello(struct OlsrHello *Msg, int UseLq)
405 {
406         int Size, LinkSize;
407         struct OlsrHelloLink *Link;
408         unsigned int *Addr;
409
410         Msg->Header.SeqNo = ::ntohs(Msg->Header.SeqNo);
411
412         AddNode(Msg->Header.Orig, Msg->Header.VTime);
413
414         Size = Msg->Header.Size;
415
416         Size -= sizeof (struct OlsrHello);
417
418         Link = (struct OlsrHelloLink *)(Msg + 1);
419
420         while (Size > 0)
421         {
422                 Link->Size = ::ntohs(Link->Size);
423
424                 LinkSize = Link->Size;
425
426                 Size -= LinkSize;
427
428                 LinkSize -= sizeof (struct OlsrHelloLink);
429
430                 Addr = (unsigned int *)(Link + 1);
431
432                 while (LinkSize > 0)
433                 {
434                         LinkSize -= 4;
435
436                         AddNode(*Addr, Msg->Header.VTime);
437
438                         if ((Link->LinkCode & 0x0c) == 0x08)
439                                 AddMpr(*Addr, Msg->Header.Orig, Msg->Header.VTime);
440
441                         Addr++;
442
443                         if (UseLq != 0)
444                         {
445                                 LinkSize -= 4;
446                                 Addr++;
447                         }
448                 }
449
450                 Link = (struct OlsrHelloLink *)Addr;
451         }
452 }
453
454 void CFrontendDlg::HandleIpcRoute(struct IpcRoute *Msg)
455 {
456         if (Msg->Header.Size != sizeof (struct IpcRoute))
457                 return;
458
459         if (Msg->Add == 0)
460                 m_TabCtrl.m_Dialog4.DeleteRoute(Msg->Dest.v4);
461
462         else
463                 m_TabCtrl.m_Dialog4.AddRoute(Msg->Dest.v4, Msg->Gate.v4, Msg->Metric,
464                 Msg->Int);
465 }
466
467 void CFrontendDlg::HandleIpcConfig(struct IpcConfig *Msg)
468 {
469         if (Msg->Header.Size != sizeof (struct IpcConfig))
470                 return;
471
472         Msg->HelloInt = ::ntohs(Msg->HelloInt);
473         Msg->WiredHelloInt = ::ntohs(Msg->WiredHelloInt);
474         Msg->TcInt = ::ntohs(Msg->TcInt);
475
476         Msg->HelloHold = ::ntohs(Msg->HelloHold);
477         Msg->TcHold = ::ntohs(Msg->TcHold);
478
479         LocalHost = Msg->MainAddr.v4;
480 }
481
482 static int FullRead(SOCKET SockHand, char *Buff, int Len)
483 {
484         int Res;
485
486         do
487         {
488                 Res = ::recv(SockHand, Buff, Len, 0);
489
490                 if (Res <= 0)
491                         return -1;
492
493                 Len -= Res;
494                 Buff += Res;
495         }
496         while (Len > 0);
497
498         return 0;
499 }
500
501 // XXX - we should have access to olsrd's internal data structures instead
502
503 unsigned int CFrontendDlg::NetThreadFunc(void)
504 {
505         struct IpcHeader Header;
506         int Res;
507         char *Msg;
508
509         for (;;)
510         {
511                 Res = FullRead(SockHand, (char *)&Header, sizeof (struct IpcHeader));
512
513                 if (Res < 0)
514                         break;
515
516                 Header.Size = ntohs(Header.Size);
517
518                 Msg = new char [Header.Size];
519
520                 ::memcpy(Msg, &Header, sizeof (struct IpcHeader));
521
522                 Res = FullRead(SockHand, Msg + sizeof (struct IpcHeader),
523                         Header.Size - sizeof (struct IpcHeader));
524
525                 if (Res < 0)
526                         break;
527
528                 SYSTEMTIME SysTime;
529                 FILETIME FileTime;
530
531                 ::GetSystemTime(&SysTime);
532                 ::SystemTimeToFileTime(&SysTime, &FileTime);
533
534                 Now = *(unsigned __int64 *)&FileTime;
535
536                 switch (Header.Type)
537                 {
538                 case MSG_TYPE_IPC_ROUTE:
539                         HandleIpcRoute((struct IpcRoute *)Msg);
540                         break;
541
542                 case MSG_TYPE_IPC_CONFIG:
543                         HandleIpcConfig((struct IpcConfig *)Msg);
544                         break;
545
546                 case MSG_TYPE_OLSR_HELLO:
547                         HandleOlsrHello((struct OlsrHello *)Msg, 0);
548                         break;
549
550                 case MSG_TYPE_OLSR_TC:
551                         HandleOlsrTc((struct OlsrTc *)Msg, 0);
552                         break;
553
554                 case MSG_TYPE_OLSR_MID:
555                         HandleOlsrMid((struct OlsrHeader *)Msg);
556                         break;
557
558                 case MSG_TYPE_OLSR_HNA:
559                         HandleOlsrHna((struct OlsrHeader *)Msg);
560                         break;
561
562                 case MSG_TYPE_OLSR_LQ_HELLO:
563                         HandleOlsrHello((struct OlsrHello *)Msg, 1);
564                         break;
565
566                 case MSG_TYPE_OLSR_LQ_TC:
567                         HandleOlsrTc((struct OlsrTc *)Msg, 1);
568                         break;
569                 }
570
571                 delete[] Msg;
572
573                 // XXX - nodes are only timed out while messages keep coming in
574
575                 Timeout();
576         }
577
578         AfxEndThread(0);
579         return 0;
580 }
581
582 unsigned int CFrontendDlg::LogThreadFunc(void)
583 {
584         char Buff[1000];
585         int Len;
586         int Left, Right;
587         CString Line;
588         CString Int;
589
590         while (::ReadFile(OutRead, Buff, sizeof (Buff) - 1, (unsigned long *)&Len, NULL))
591         {
592                 if (Len == 0)
593                         break;
594
595                 Left = 0;
596
597                 for (Right = 0; Right < Len; Right++)
598                 {
599                         if (Buff[Right] != 13)
600                                 Buff[Left++] = Buff[Right];
601                 }
602
603                 Len = Left;
604
605                 Left = 0;
606
607                 for (Right = 0; Right < Len; Right++)
608                 {
609                         if (Buff[Right] == 10)
610                         {
611                                 Buff[Right] = 0;
612                                 Line += (Buff + Left);
613
614                                 if (PipeMode == PIPE_MODE_RUN)
615                                         m_TabCtrl.m_Dialog1.AddOutputLine(Line);
616
617                                 else if (Line.GetLength() > 8 && Line[0] == 'i' && Line[1] == 'f')
618                                 {
619                                         Int = Line.Mid(0, 4);
620                                         Int.MakeUpper();
621
622                                         Interfaces.Add(Int);
623                                         IsWlan.Add(Line.Mid(6, 1));
624                                         Addresses.Add(Line.Mid(8));
625                                 }
626
627                                 Line.Empty();
628
629                                 Left = Right + 1;
630                         }
631                 }
632
633                 Buff[Right] = 0;
634                 Line += (Buff + Left);
635         }
636
637         if (PipeMode == PIPE_MODE_RUN)
638         {
639                 m_StopButton.EnableWindow(FALSE);
640                 m_StartButton.EnableWindow(TRUE);
641         }
642
643         AfxEndThread(0);
644         return 0;
645 }
646
647 static unsigned int LogThreadStub(void *Arg)
648 {
649         class CFrontendDlg *This;
650
651         This = (class CFrontendDlg *)Arg;
652
653         return This->LogThreadFunc();
654 }
655
656 static unsigned int NetThreadStub(void *Arg)
657 {
658         class CFrontendDlg *This;
659
660         This = (class CFrontendDlg *)Arg;
661
662         return This->NetThreadFunc();
663 }
664
665 int CFrontendDlg::ExecutePipe(const char *CmdLine, HANDLE *InWrite,
666                                                           HANDLE *OutRead, HANDLE *ShimProc)
667 {
668         SECURITY_ATTRIBUTES SecAttr;
669         HANDLE OutWrite, OutReadTmp;
670         HANDLE ErrWrite;
671         HANDLE InRead, InWriteTmp;
672         HANDLE Proc;
673         STARTUPINFO StartupInfo;
674         PROCESS_INFORMATION ProcessInfo;
675
676         SecAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
677         SecAttr.lpSecurityDescriptor = NULL;
678         SecAttr.bInheritHandle = TRUE;
679
680         Proc = ::GetCurrentProcess();
681
682         if (!::CreatePipe(&OutReadTmp, &OutWrite, &SecAttr, 0))
683         {
684                 AfxMessageBox("Cannot create stdout pipe.");
685                 return -1;
686         }
687
688         if (!::DuplicateHandle(Proc, OutReadTmp, Proc, OutRead,
689                 0, FALSE, DUPLICATE_SAME_ACCESS))
690         {
691                 AfxMessageBox("Cannot duplicate temporary stdout read handle.");
692                 return -1;
693         }
694
695         if (!::CloseHandle(OutReadTmp))
696         {
697                 AfxMessageBox("Cannot close temporary stdout read handle.");
698                 return -1;
699         }
700
701         if (!::CreatePipe(&InRead, &InWriteTmp, &SecAttr, 0))
702         {
703                 AfxMessageBox("Cannot create stdin pipe.");
704                 return -1;
705         }
706
707         if (!::DuplicateHandle(Proc, InWriteTmp, Proc, InWrite,
708                 0, FALSE, DUPLICATE_SAME_ACCESS))
709         {
710                 AfxMessageBox("Cannot duplicate temporary stdin write handle.");
711                 return -1;
712         }
713
714         if (!::CloseHandle(InWriteTmp))
715         {
716                 AfxMessageBox("Cannot close temporary stdin write handle.");
717                 return -1;
718         }
719
720         if (!::DuplicateHandle(Proc, OutWrite, Proc, &ErrWrite,
721                 0, TRUE, DUPLICATE_SAME_ACCESS))
722         {
723                 AfxMessageBox("Cannot duplicate stdout write handle for stderr.");
724                 return -1;
725         }
726
727         ::memset(&StartupInfo, 0, sizeof (STARTUPINFO));
728
729         StartupInfo.cb = sizeof (STARTUPINFO);
730
731         StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
732
733         StartupInfo.hStdInput = InRead;
734         StartupInfo.hStdOutput = OutWrite;
735         StartupInfo.hStdError = ErrWrite;
736
737         StartupInfo.wShowWindow = SW_HIDE;
738
739         if (!::CreateProcess(NULL, (char *)CmdLine, NULL, NULL, TRUE,
740                 0, NULL, NULL, &StartupInfo, &ProcessInfo))
741         {
742                 AfxMessageBox("Cannot create OLSR server process.");
743                 return -1;
744         }
745
746         if (!::CloseHandle(InRead))
747         {
748                 AfxMessageBox("Cannot close stdin read handle.");
749                 return -1;
750         }
751
752         if (!::CloseHandle(OutWrite))
753         {
754                 AfxMessageBox("Cannot close stdout write handle.");
755                 return -1;
756         }
757
758         if (!::CloseHandle(ErrWrite))
759         {
760                 AfxMessageBox("Cannot close stderr write handle.");
761                 return -1;
762         }
763
764         *ShimProc = ProcessInfo.hProcess;
765
766         return 0;
767 }
768
769 int CFrontendDlg::GetInterfaces()
770 {
771         char GuiPath[MAX_PATH];
772         CString CmdLine;
773         CWinThread *IntThread;
774
775         ::GetModuleFileName(NULL, GuiPath, MAX_PATH);
776
777         CmdLine = GuiPath;
778         CmdLine = CmdLine.Mid(0, CmdLine.ReverseFind('\\')) + "\\olsrd.exe -int";
779
780         if (ExecutePipe((const char *)CmdLine, &InWrite, &OutRead, &ShimProc) < 0)
781         {
782                 AfxMessageBox("Cannot execute '" + CmdLine + "'.");
783                 return -1;
784         }
785
786         PipeMode = PIPE_MODE_INT;
787
788         IntThread = AfxBeginThread(LogThreadStub, (void *)this);
789
790         ::WaitForSingleObject((HANDLE)(*IntThread), INFINITE);
791
792         return 0;
793 }
794
795 int CFrontendDlg::StartOlsrd()
796 {
797         WSADATA WsaData;
798         CString CmdLine;
799         char Path[MAX_PATH];
800         char TempPath[MAX_PATH];
801         int Try;
802
803         m_TabCtrl.m_Dialog3.ClearNodeInfo();
804         m_TabCtrl.m_Dialog4.ClearRoutes();
805
806         if (WSAStartup(0x0202, &WsaData))
807         {
808                 AfxMessageBox("Cannot initialize WinSock library.");
809                 return -1;
810         }
811
812         ::GetModuleFileName(NULL, Path, MAX_PATH);
813
814         CmdLine = Path;
815         CmdLine = CmdLine.Mid(0, CmdLine.ReverseFind('\\')) + "\\Shim.exe";
816
817         ::GetTempPath(MAX_PATH - 16, Path);
818         ::GetTempFileName(Path, "GNU", 0, TempPath);
819
820         StoredTempFile = TempPath;
821
822         if (m_TabCtrl.m_Dialog2.SaveConfigFile(StoredTempFile, 0) < 0)
823         {
824                 AfxMessageBox("Cannot save temporary configuration file '" + 
825                         StoredTempFile + "'.");
826                 return -1;
827         }
828
829         CmdLine += " -f " + StoredTempFile;
830
831         if (ExecutePipe((const char *)CmdLine, &InWrite, &OutRead, &ShimProc) < 0)
832         {
833                 AfxMessageBox("Cannot execute '" + CmdLine + "'.");
834                 return -1;
835         }
836
837         PipeMode = PIPE_MODE_RUN;
838
839         LogThread = AfxBeginThread(LogThreadStub, (void *)this);
840
841         struct sockaddr_in Addr;
842
843         Addr.sin_family = AF_INET;
844         Addr.sin_port = ::htons(1212);
845         Addr.sin_addr.s_addr = ::inet_addr("127.0.0.1");
846
847         SockHand = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
848
849         if (SockHand < 0)
850         {
851                 AfxMessageBox("Cannot create IPC socket.");
852
853                 ::SetEvent(Event);
854                 ::WaitForSingleObject((HANDLE)LogThread, INFINITE);
855
856                 LogThread = NULL;
857
858                 return -1;
859         }
860
861         for (Try = 0; Try < 5; Try++)
862         {
863                 if (::connect(SockHand, (struct sockaddr *)&Addr,
864                         sizeof (struct sockaddr_in)) >= 0)
865                         break;
866
867                 ::Sleep(500);
868         }
869
870         if (Try == 10)
871         {
872                 AfxMessageBox("Cannot connect to IPC port.");
873
874                 ::SetEvent(Event);
875                 ::WaitForSingleObject((HANDLE)LogThread, INFINITE);
876
877                 ::closesocket(SockHand);
878
879                 LogThread = NULL;
880
881                 return -1;
882         }
883
884         NetThread = AfxBeginThread(NetThreadStub, (void *)this);
885
886         return 0;
887 }
888
889 int CFrontendDlg::StopOlsrd()
890 {
891         if (LogThread == NULL && NetThread == NULL)
892                 return 0;
893
894         TrayIcon::getInstance()->setStatus( TrayIcon::OFF, "Off" );
895
896         ::SetEvent(Event);
897
898         ::WaitForSingleObject((HANDLE)LogThread, INFINITE);
899         ::WaitForSingleObject((HANDLE)NetThread, INFINITE);
900
901         LogThread = NULL;
902         NetThread = NULL;
903
904         ::DeleteFile(StoredTempFile);
905
906         return 0;
907 }
908
909 BOOL CFrontendDlg::OnInitDialog()
910 {
911         HICON Small, Large;
912
913         CDialog::OnInitDialog();
914
915         Small = (HICON)::LoadImage(AfxGetApp()->m_hInstance,
916                 MAKEINTRESOURCE(IDI_ICON1),
917                 IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),
918                 GetSystemMetrics(SM_CYSMICON), 0);
919
920         Large = (HICON)::LoadImage(AfxGetApp()->m_hInstance,
921                 MAKEINTRESOURCE(IDI_ICON1),
922                 IMAGE_ICON, GetSystemMetrics(SM_CXICON),
923                 GetSystemMetrics(SM_CYICON), 0);
924
925         SetIcon(Small, FALSE);
926         SetIcon(Large, TRUE);
927
928         GetInterfaces();
929
930         m_TabCtrl.InsertItem(0, "Settings");
931         m_TabCtrl.InsertItem(1, "Output");
932         m_TabCtrl.InsertItem(2, "Nodes");
933         m_TabCtrl.InsertItem(3, "Routes");
934
935         m_TabCtrl.InitTabDialogs(&Interfaces, &Addresses, &IsWlan);
936
937         m_StopButton.EnableWindow(FALSE);
938
939         if (!ConfigFile.IsEmpty())
940         {
941                 if (m_TabCtrl.m_Dialog2.OpenConfigFile(ConfigFile) < 0)
942                         AfxMessageBox("Cannot open configuration file '" + ConfigFile + "'.");
943
944                 else
945                 {
946                         OnStartButton();
947
948                         m_TabCtrl.SetCurSel(1);
949                         m_TabCtrl.DisplayTabDialog();
950                 }
951         }
952
953         return TRUE;
954 }
955
956 void CFrontendDlg::OnOK()
957 {
958 }
959
960 void CFrontendDlg::OnCancel()
961 {
962         OnExitButton();
963 }
964
965 void CFrontendDlg::OnStartButton() 
966 {
967         m_StartButton.EnableWindow(FALSE);
968
969         m_TabCtrl.m_Dialog1.SetFrozen(1);
970
971         if (StartOlsrd() < 0)
972         {
973                 m_TabCtrl.m_Dialog1.SetFrozen(0);
974                 m_TabCtrl.m_Dialog1.AddOutputLine("");
975
976                 AfxMessageBox("Cannot start OLSR server.");
977
978                 m_StartButton.EnableWindow(TRUE);
979
980                 return;
981         }
982
983         m_TabCtrl.m_Dialog1.HandleStart();
984
985         m_StopButton.EnableWindow(TRUE);
986 }
987
988 void CFrontendDlg::OnStopButton() 
989 {
990         if (StopOlsrd() < 0)
991                 return;
992
993         m_TabCtrl.m_Dialog1.HandleStop();
994
995         m_StopButton.EnableWindow(FALSE);
996         m_StartButton.EnableWindow(TRUE);
997 }
998
999 void CFrontendDlg::OnExitButton()
1000 {
1001         delete TrayIcon::getInstance();
1002
1003         if (StopOlsrd() < 0)
1004                 return;
1005
1006         m_TabCtrl.m_Dialog3.ClearNodeInfo();
1007         m_TabCtrl.m_Dialog4.ClearRoutes();
1008
1009         DestroyWindow();
1010 }
1011
1012 #endif /* _WIN32 */