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