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