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