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