efd7ddc89ff48651a7f1298f2c1de813e4f752b9
[olsrd.git] / gui / win32 / Main / FrontendDlg.cpp
1 /*\r
2  * $Id: FrontendDlg.cpp,v 1.7 2004/11/20 23:17:47 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, int UseLq)\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                 if (UseLq != 0)\r
317                 {\r
318                         Size -= 4;\r
319                         Addr++;\r
320                 }\r
321 \r
322         }\r
323 }\r
324 \r
325 void CFrontendDlg::HandleOlsrMid(struct OlsrHeader *Msg)\r
326 {\r
327         int Size;\r
328         unsigned int *Addr;\r
329 \r
330         Msg->SeqNo = ::ntohs(Msg->SeqNo);\r
331 \r
332         AddNode(Msg->Orig, Msg->VTime);\r
333 \r
334         Size = Msg->Size;\r
335 \r
336         Size -= sizeof (struct OlsrHeader);\r
337 \r
338         Addr = (unsigned int *)(Msg + 1);\r
339 \r
340         while (Size > 0)\r
341         {\r
342                 Size -= 4;\r
343 \r
344                 AddMid(*Addr, Msg->Orig, Msg->VTime);\r
345 \r
346                 Addr++;\r
347         }\r
348 }\r
349 \r
350 void CFrontendDlg::HandleOlsrHna(struct OlsrHeader *Msg)\r
351 {\r
352         int Size;\r
353         unsigned int *Addr;\r
354 \r
355         Msg->SeqNo = ::ntohs(Msg->SeqNo);\r
356 \r
357         AddNode(Msg->Orig, Msg->VTime);\r
358 \r
359         Size = Msg->Size;\r
360 \r
361         Size -= sizeof (struct OlsrHeader);\r
362 \r
363         Addr = (unsigned int *)(Msg + 1);\r
364 \r
365         while (Size > 0)\r
366         {\r
367                 Size -= 8;\r
368 \r
369                 AddHna(Addr[0], Addr[1], Msg->Orig, Msg->VTime);\r
370 \r
371                 Addr += 2;\r
372         }\r
373 }\r
374 \r
375 void CFrontendDlg::HandleOlsrHello(struct OlsrHello *Msg, int UseLq)\r
376 {\r
377         int Size, LinkSize;\r
378         struct OlsrHelloLink *Link;\r
379         unsigned int *Addr;\r
380 \r
381         Msg->Header.SeqNo = ::ntohs(Msg->Header.SeqNo);\r
382 \r
383         AddNode(Msg->Header.Orig, Msg->Header.VTime);\r
384 \r
385         Size = Msg->Header.Size;\r
386 \r
387         Size -= sizeof (struct OlsrHello);\r
388 \r
389         Link = (struct OlsrHelloLink *)(Msg + 1);\r
390 \r
391         while (Size > 0)\r
392         {\r
393                 Link->Size = ::ntohs(Link->Size);\r
394 \r
395                 LinkSize = Link->Size;\r
396 \r
397                 Size -= LinkSize;\r
398 \r
399                 LinkSize -= sizeof (struct OlsrHelloLink);\r
400 \r
401                 Addr = (unsigned int *)(Link + 1);\r
402 \r
403                 while (LinkSize > 0)\r
404                 {\r
405                         LinkSize -= 4;\r
406 \r
407                         AddNode(*Addr, Msg->Header.VTime);\r
408 \r
409                         if ((Link->LinkCode & 0x0c) == 0x08)\r
410                                 AddMpr(*Addr, Msg->Header.Orig, Msg->Header.VTime);\r
411 \r
412                         Addr++;\r
413 \r
414                         if (UseLq != 0)\r
415                         {\r
416                                 LinkSize -= 4;\r
417                                 Addr++;\r
418                         }\r
419                 }\r
420 \r
421                 Link = (struct OlsrHelloLink *)Addr;\r
422         }\r
423 }\r
424 \r
425 void CFrontendDlg::HandleIpcRoute(struct IpcRoute *Msg)\r
426 {\r
427         if (Msg->Header.Size != sizeof (struct IpcRoute))\r
428                 return;\r
429 \r
430         if (Msg->Add == 0)\r
431                 m_TabCtrl.m_Dialog4.DeleteRoute(Msg->Dest.v4);\r
432 \r
433         else\r
434                 m_TabCtrl.m_Dialog4.AddRoute(Msg->Dest.v4, Msg->Gate.v4, Msg->Metric,\r
435                 Msg->Int);\r
436 }\r
437 \r
438 void CFrontendDlg::HandleIpcConfig(struct IpcConfig *Msg)\r
439 {\r
440         if (Msg->Header.Size != sizeof (struct IpcConfig))\r
441                 return;\r
442 \r
443         Msg->HelloInt = ::ntohs(Msg->HelloInt);\r
444         Msg->WiredHelloInt = ::ntohs(Msg->WiredHelloInt);\r
445         Msg->TcInt = ::ntohs(Msg->TcInt);\r
446 \r
447         Msg->HelloHold = ::ntohs(Msg->HelloHold);\r
448         Msg->TcHold = ::ntohs(Msg->TcHold);\r
449 \r
450         LocalHost = Msg->MainAddr.v4;\r
451 }\r
452 \r
453 static int FullRead(SOCKET SockHand, char *Buff, int Len)\r
454 {\r
455         int Res;\r
456 \r
457         do\r
458         {\r
459                 Res = ::recv(SockHand, Buff, Len, 0);\r
460 \r
461                 if (Res <= 0)\r
462                         return -1;\r
463 \r
464                 Len -= Res;\r
465                 Buff += Res;\r
466         }\r
467         while (Len > 0);\r
468 \r
469         return 0;\r
470 }\r
471 \r
472 // XXX - we should have access to olsrd's internal data structures instead\r
473 \r
474 unsigned int CFrontendDlg::NetThreadFunc(void)\r
475 {\r
476         struct IpcHeader Header;\r
477         int Res;\r
478         char *Msg;\r
479 \r
480         for (;;)\r
481         {\r
482                 Res = FullRead(SockHand, (char *)&Header, sizeof (struct IpcHeader));\r
483 \r
484                 if (Res < 0)\r
485                         break;\r
486 \r
487                 Header.Size = ntohs(Header.Size);\r
488 \r
489                 Msg = new char [Header.Size];\r
490 \r
491                 ::memcpy(Msg, &Header, sizeof (struct IpcHeader));\r
492 \r
493                 Res = FullRead(SockHand, Msg + sizeof (struct IpcHeader),\r
494                         Header.Size - sizeof (struct IpcHeader));\r
495 \r
496                 if (Res < 0)\r
497                         break;\r
498 \r
499                 SYSTEMTIME SysTime;\r
500                 FILETIME FileTime;\r
501 \r
502                 ::GetSystemTime(&SysTime);\r
503                 ::SystemTimeToFileTime(&SysTime, &FileTime);\r
504 \r
505                 Now = *(unsigned __int64 *)&FileTime;\r
506 \r
507                 switch (Header.Type)\r
508                 {\r
509                 case MSG_TYPE_IPC_ROUTE:\r
510                         HandleIpcRoute((struct IpcRoute *)Msg);\r
511                         break;\r
512 \r
513                 case MSG_TYPE_IPC_CONFIG:\r
514                         HandleIpcConfig((struct IpcConfig *)Msg);\r
515                         break;\r
516 \r
517                 case MSG_TYPE_OLSR_HELLO:\r
518                         HandleOlsrHello((struct OlsrHello *)Msg, 0);\r
519                         break;\r
520 \r
521                 case MSG_TYPE_OLSR_TC:\r
522                         HandleOlsrTc((struct OlsrTc *)Msg, 0);\r
523                         break;\r
524 \r
525                 case MSG_TYPE_OLSR_MID:\r
526                         HandleOlsrMid((struct OlsrHeader *)Msg);\r
527                         break;\r
528 \r
529                 case MSG_TYPE_OLSR_HNA:\r
530                         HandleOlsrHna((struct OlsrHeader *)Msg);\r
531                         break;\r
532 \r
533                 case MSG_TYPE_OLSR_LQ_HELLO:\r
534                         HandleOlsrHello((struct OlsrHello *)Msg, 1);\r
535                         break;\r
536 \r
537                 case MSG_TYPE_OLSR_LQ_TC:\r
538                         HandleOlsrTc((struct OlsrTc *)Msg, 1);\r
539                         break;\r
540                 }\r
541 \r
542                 delete[] Msg;\r
543 \r
544                 // XXX - nodes are only timed out while messages keep coming in\r
545 \r
546                 Timeout();\r
547         }\r
548 \r
549         AfxEndThread(0);\r
550         return 0;\r
551 }\r
552 \r
553 unsigned int CFrontendDlg::LogThreadFunc(void)\r
554 {\r
555         char Buff[1000];\r
556         int Len;\r
557         int Left, Right;\r
558         CString Line;\r
559         CString Int;\r
560 \r
561         while (::ReadFile(OutRead, Buff, sizeof (Buff) - 1, (unsigned long *)&Len, NULL))\r
562         {\r
563                 if (Len == 0)\r
564                         break;\r
565 \r
566                 Left = 0;\r
567 \r
568                 for (Right = 0; Right < Len; Right++)\r
569                 {\r
570                         if (Buff[Right] != 13)\r
571                                 Buff[Left++] = Buff[Right];\r
572                 }\r
573 \r
574                 Len = Left;\r
575 \r
576                 Left = 0;\r
577 \r
578                 for (Right = 0; Right < Len; Right++)\r
579                 {\r
580                         if (Buff[Right] == 10)\r
581                         {\r
582                                 Buff[Right] = 0;\r
583                                 Line += (Buff + Left);\r
584 \r
585                                 if (PipeMode == PIPE_MODE_RUN)\r
586                                         m_TabCtrl.m_Dialog1.AddOutputLine(Line);\r
587 \r
588                                 else if (Line.GetLength() > 8 && Line[0] == 'i' && Line[1] == 'f')\r
589                                 {\r
590                                         Int = Line.Mid(0, 4);\r
591                                         Int.MakeUpper();\r
592 \r
593                                         Interfaces.Add(Int);\r
594                                         IsWlan.Add(Line.Mid(6, 1));\r
595                                         Addresses.Add(Line.Mid(8));\r
596                                 }\r
597 \r
598                                 Line.Empty();\r
599 \r
600                                 Left = Right + 1;\r
601                         }\r
602                 }\r
603 \r
604                 Buff[Right] = 0;\r
605                 Line += (Buff + Left);\r
606         }\r
607 \r
608         if (PipeMode == PIPE_MODE_RUN)\r
609         {\r
610                 m_StopButton.EnableWindow(FALSE);\r
611                 m_StartButton.EnableWindow(TRUE);\r
612         }\r
613 \r
614         AfxEndThread(0);\r
615         return 0;\r
616 }\r
617 \r
618 static unsigned int LogThreadStub(void *Arg)\r
619 {\r
620         class CFrontendDlg *This;\r
621 \r
622         This = (class CFrontendDlg *)Arg;\r
623 \r
624         return This->LogThreadFunc();\r
625 }\r
626 \r
627 static unsigned int NetThreadStub(void *Arg)\r
628 {\r
629         class CFrontendDlg *This;\r
630 \r
631         This = (class CFrontendDlg *)Arg;\r
632 \r
633         return This->NetThreadFunc();\r
634 }\r
635 \r
636 int CFrontendDlg::ExecutePipe(const char *CmdLine, HANDLE *InWrite,\r
637                                                           HANDLE *OutRead, HANDLE *ShimProc)\r
638 {\r
639         SECURITY_ATTRIBUTES SecAttr;\r
640         HANDLE OutWrite, OutReadTmp;\r
641         HANDLE ErrWrite;\r
642         HANDLE InRead, InWriteTmp;\r
643         HANDLE Proc;\r
644         STARTUPINFO StartupInfo;\r
645         PROCESS_INFORMATION ProcessInfo;\r
646 \r
647         SecAttr.nLength = sizeof (SECURITY_ATTRIBUTES);\r
648         SecAttr.lpSecurityDescriptor = NULL;\r
649         SecAttr.bInheritHandle = TRUE;\r
650 \r
651         Proc = ::GetCurrentProcess();\r
652 \r
653         if (!::CreatePipe(&OutReadTmp, &OutWrite, &SecAttr, 0))\r
654         {\r
655                 AfxMessageBox("Cannot create stdout pipe.");\r
656                 return -1;\r
657         }\r
658 \r
659         if (!::DuplicateHandle(Proc, OutReadTmp, Proc, OutRead,\r
660                 0, FALSE, DUPLICATE_SAME_ACCESS))\r
661         {\r
662                 AfxMessageBox("Cannot duplicate temporary stdout read handle.");\r
663                 return -1;\r
664         }\r
665 \r
666         if (!::CloseHandle(OutReadTmp))\r
667         {\r
668                 AfxMessageBox("Cannot close temporary stdout read handle.");\r
669                 return -1;\r
670         }\r
671 \r
672         if (!::CreatePipe(&InRead, &InWriteTmp, &SecAttr, 0))\r
673         {\r
674                 AfxMessageBox("Cannot create stdin pipe.");\r
675                 return -1;\r
676         }\r
677 \r
678         if (!::DuplicateHandle(Proc, InWriteTmp, Proc, InWrite,\r
679                 0, FALSE, DUPLICATE_SAME_ACCESS))\r
680         {\r
681                 AfxMessageBox("Cannot duplicate temporary stdin write handle.");\r
682                 return -1;\r
683         }\r
684 \r
685         if (!::CloseHandle(InWriteTmp))\r
686         {\r
687                 AfxMessageBox("Cannot close temporary stdin write handle.");\r
688                 return -1;\r
689         }\r
690 \r
691         if (!::DuplicateHandle(Proc, OutWrite, Proc, &ErrWrite,\r
692                 0, TRUE, DUPLICATE_SAME_ACCESS))\r
693         {\r
694                 AfxMessageBox("Cannot duplicate stdout write handle for stderr.");\r
695                 return -1;\r
696         }\r
697 \r
698         ::memset(&StartupInfo, 0, sizeof (STARTUPINFO));\r
699 \r
700         StartupInfo.cb = sizeof (STARTUPINFO);\r
701 \r
702         StartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;\r
703 \r
704         StartupInfo.hStdInput = InRead;\r
705         StartupInfo.hStdOutput = OutWrite;\r
706         StartupInfo.hStdError = ErrWrite;\r
707 \r
708         StartupInfo.wShowWindow = SW_HIDE;\r
709 \r
710         if (!::CreateProcess(NULL, (char *)CmdLine, NULL, NULL, TRUE,\r
711                 0, NULL, NULL, &StartupInfo, &ProcessInfo))\r
712         {\r
713                 AfxMessageBox("Cannot create OLSR server process.");\r
714                 return -1;\r
715         }\r
716 \r
717         if (!::CloseHandle(InRead))\r
718         {\r
719                 AfxMessageBox("Cannot close stdin read handle.");\r
720                 return -1;\r
721         }\r
722 \r
723         if (!::CloseHandle(OutWrite))\r
724         {\r
725                 AfxMessageBox("Cannot close stdout write handle.");\r
726                 return -1;\r
727         }\r
728 \r
729         if (!::CloseHandle(ErrWrite))\r
730         {\r
731                 AfxMessageBox("Cannot close stderr write handle.");\r
732                 return -1;\r
733         }\r
734 \r
735         *ShimProc = ProcessInfo.hProcess;\r
736 \r
737         return 0;\r
738 }\r
739 \r
740 int CFrontendDlg::GetInterfaces()\r
741 {\r
742         char GuiPath[MAX_PATH];\r
743         CString CmdLine;\r
744         CWinThread *IntThread;\r
745 \r
746         ::GetModuleFileName(NULL, GuiPath, MAX_PATH);\r
747 \r
748         CmdLine = GuiPath;\r
749         CmdLine = CmdLine.Mid(0, CmdLine.ReverseFind('\\')) + "\\olsrd.exe -int";\r
750 \r
751         if (ExecutePipe((const char *)CmdLine, &InWrite, &OutRead, &ShimProc) < 0)\r
752         {\r
753                 AfxMessageBox("Cannot execute '" + CmdLine + "'.");\r
754                 return -1;\r
755         }\r
756 \r
757         PipeMode = PIPE_MODE_INT;\r
758 \r
759         IntThread = AfxBeginThread(LogThreadStub, (void *)this);\r
760 \r
761         ::WaitForSingleObject((HANDLE)(*IntThread), INFINITE);\r
762 \r
763         return 0;\r
764 }\r
765 \r
766 int CFrontendDlg::StartOlsrd()\r
767 {\r
768         WSADATA WsaData;\r
769         CString CmdLine;\r
770         char Path[MAX_PATH];\r
771         char TempPath[MAX_PATH];\r
772         int Try;\r
773 \r
774         m_TabCtrl.m_Dialog3.ClearNodeInfo();\r
775         m_TabCtrl.m_Dialog4.ClearRoutes();\r
776 \r
777         if (WSAStartup(0x0202, &WsaData))\r
778         {\r
779                 AfxMessageBox("Cannot initialize WinSock library.");\r
780                 return -1;\r
781         }\r
782 \r
783         ::GetModuleFileName(NULL, Path, MAX_PATH);\r
784 \r
785         CmdLine = Path;\r
786         CmdLine = CmdLine.Mid(0, CmdLine.ReverseFind('\\')) + "\\Shim.exe";\r
787 \r
788         ::GetTempPath(MAX_PATH - 16, Path);\r
789         ::GetTempFileName(Path, "GNU", 0, TempPath);\r
790 \r
791         StoredTempFile = TempPath;\r
792 \r
793         if (m_TabCtrl.m_Dialog2.SaveConfigFile(StoredTempFile, 0) < 0)\r
794         {\r
795                 AfxMessageBox("Cannot save temporary configuration file '" + \r
796                         StoredTempFile + "'.");\r
797                 return -1;\r
798         }\r
799 \r
800         CmdLine += " -f " + StoredTempFile;\r
801 \r
802         if (ExecutePipe((const char *)CmdLine, &InWrite, &OutRead, &ShimProc) < 0)\r
803         {\r
804                 AfxMessageBox("Cannot execute '" + CmdLine + "'.");\r
805                 return -1;\r
806         }\r
807 \r
808         PipeMode = PIPE_MODE_RUN;\r
809 \r
810         LogThread = AfxBeginThread(LogThreadStub, (void *)this);\r
811 \r
812         struct sockaddr_in Addr;\r
813 \r
814         Addr.sin_family = AF_INET;\r
815         Addr.sin_port = ::htons(1212);\r
816         Addr.sin_addr.s_addr = ::inet_addr("127.0.0.1");\r
817 \r
818         SockHand = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\r
819 \r
820         if (SockHand < 0)\r
821         {\r
822                 AfxMessageBox("Cannot create IPC socket.");\r
823 \r
824                 ::SetEvent(Event);\r
825                 ::WaitForSingleObject((HANDLE)LogThread, INFINITE);\r
826 \r
827                 return -1;\r
828         }\r
829 \r
830         for (Try = 0; Try < 5; Try++)\r
831         {\r
832                 if (::connect(SockHand, (struct sockaddr *)&Addr,\r
833                         sizeof (struct sockaddr_in)) >= 0)\r
834                         break;\r
835 \r
836                 ::Sleep(500);\r
837         }\r
838 \r
839         if (Try == 10)\r
840         {\r
841                 AfxMessageBox("Cannot connect to IPC port.");\r
842 \r
843                 ::SetEvent(Event);\r
844                 ::WaitForSingleObject((HANDLE)LogThread, INFINITE);\r
845 \r
846                 ::closesocket(SockHand);\r
847 \r
848                 return -1;\r
849         }\r
850 \r
851         NetThread = AfxBeginThread(NetThreadStub, (void *)this);\r
852 \r
853         return 0;\r
854 }\r
855 \r
856 int CFrontendDlg::StopOlsrd()\r
857 {\r
858         ::SetEvent(Event);\r
859 \r
860         ::WaitForSingleObject((HANDLE)LogThread, INFINITE);\r
861         ::WaitForSingleObject((HANDLE)NetThread, INFINITE);\r
862 \r
863         ::DeleteFile(StoredTempFile);\r
864 \r
865         return 0;\r
866 }\r
867 \r
868 BOOL CFrontendDlg::OnInitDialog()\r
869 {\r
870         HICON Small, Large;\r
871 \r
872         CDialog::OnInitDialog();\r
873 \r
874         Small = (HICON)::LoadImage(AfxGetApp()->m_hInstance,\r
875                 MAKEINTRESOURCE(IDI_ICON1),\r
876                 IMAGE_ICON, GetSystemMetrics(SM_CXSMICON),\r
877                 GetSystemMetrics(SM_CYSMICON), 0);\r
878 \r
879         Large = (HICON)::LoadImage(AfxGetApp()->m_hInstance,\r
880                 MAKEINTRESOURCE(IDI_ICON1),\r
881                 IMAGE_ICON, GetSystemMetrics(SM_CXICON),\r
882                 GetSystemMetrics(SM_CYICON), 0);\r
883 \r
884         SetIcon(Small, FALSE);\r
885         SetIcon(Large, TRUE);\r
886 \r
887         GetInterfaces();\r
888 \r
889         m_TabCtrl.InsertItem(0, "Settings");\r
890         m_TabCtrl.InsertItem(1, "Output");\r
891         m_TabCtrl.InsertItem(2, "Nodes");\r
892         m_TabCtrl.InsertItem(3, "Routes");\r
893 \r
894         m_TabCtrl.InitTabDialogs(&Interfaces, &Addresses, &IsWlan);\r
895 \r
896         m_StopButton.EnableWindow(FALSE);\r
897 \r
898         if (!ConfigFile.IsEmpty())\r
899         {\r
900                 if (m_TabCtrl.m_Dialog2.OpenConfigFile(ConfigFile) < 0)\r
901                         AfxMessageBox("Cannot open configuration file '" + ConfigFile + "'.");\r
902 \r
903                 else\r
904                 {\r
905                         OnStartButton();\r
906 \r
907                         m_TabCtrl.SetCurSel(1);\r
908                         m_TabCtrl.DisplayTabDialog();\r
909                 }\r
910         }\r
911 \r
912         return TRUE;\r
913 }\r
914 \r
915 void CFrontendDlg::OnOK()\r
916 {\r
917 }\r
918 \r
919 void CFrontendDlg::OnCancel()\r
920 {\r
921         OnExitButton();\r
922 }\r
923 \r
924 void CFrontendDlg::OnStartButton() \r
925 {\r
926         m_StartButton.EnableWindow(FALSE);\r
927 \r
928         m_TabCtrl.m_Dialog1.SetFrozen(1);\r
929 \r
930         if (StartOlsrd() < 0)\r
931         {\r
932                 m_TabCtrl.m_Dialog1.SetFrozen(0);\r
933                 m_TabCtrl.m_Dialog1.AddOutputLine("");\r
934 \r
935                 AfxMessageBox("Cannot start OLSR server.");\r
936 \r
937                 m_StartButton.EnableWindow(TRUE);\r
938 \r
939                 return;\r
940         }\r
941 \r
942         m_TabCtrl.m_Dialog1.HandleStart();\r
943 \r
944         m_StopButton.EnableWindow(TRUE);\r
945 }\r
946 \r
947 void CFrontendDlg::OnStopButton() \r
948 {\r
949         if (StopOlsrd() < 0)\r
950                 return;\r
951 \r
952         m_TabCtrl.m_Dialog1.HandleStop();\r
953 \r
954         m_StopButton.EnableWindow(FALSE);\r
955         m_StartButton.EnableWindow(TRUE);\r
956 }\r
957 \r
958 void CFrontendDlg::OnExitButton()\r
959 {\r
960         if (StopOlsrd() < 0)\r
961                 return;\r
962 \r
963         m_TabCtrl.m_Dialog3.ClearNodeInfo();\r
964         m_TabCtrl.m_Dialog4.ClearRoutes();\r
965 \r
966         DestroyWindow();\r
967 }\r