Merge branch 'master' of git.ucc.asn.au:/matches/honours
[matches/honours.git] / research / transmission_spectroscopy / TOF / Win32++ / samples / Networking / ServerDlg / SvrDialog.cpp
1 ///////////////////////////////////////\r
2 // SvrDialog.cpp\r
3 \r
4 #include "stdafx.h"\r
5 #include "SvrDialog.h"\r
6 #include "DialogApp.h"\r
7 #include "resource.h"\r
8 \r
9 \r
10 /////////////////////////////////////////////\r
11 // Definitions for the CTCPClientDlg class\r
12 CTCPClientDlg::CTCPClientDlg(UINT nResID, CWnd* pParent) :\r
13                                 CDialog(nResID, pParent), m_pSocket(0)\r
14 {\r
15 }\r
16 \r
17 void CTCPClientDlg::Append(int nID, LPCTSTR buf)\r
18 {\r
19         // This function appends some text to an edit control\r
20 \r
21         // Append Line Feed\r
22         int ndx = (int)SendDlgItemMessage(nID, WM_GETTEXTLENGTH, 0, 0);\r
23         if (ndx)\r
24         {\r
25 \r
26                 SendDlgItemMessage(nID, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);\r
27                 SendDlgItemMessage(nID, EM_REPLACESEL, 0, (LPARAM) (_T( "\r\n")));\r
28         }\r
29 \r
30         // Append text\r
31         ndx = (int)SendDlgItemMessage(nID, WM_GETTEXTLENGTH, 0, 0);\r
32         SendDlgItemMessage(nID, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);\r
33         SendDlgItemMessage(nID, EM_REPLACESEL, 0, (LPARAM) buf);\r
34 }\r
35 \r
36 INT_PTR CTCPClientDlg::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
37 {\r
38         switch (uMsg)\r
39         {\r
40         case WM_CLOSE:\r
41                 // Disconnect the socket when the user closes this chat dialog\r
42                 m_pSocket->Disconnect();\r
43                 break;\r
44         }\r
45 \r
46         // Pass unhandled messages on to parent DialogProc\r
47         return DialogProcDefault(uMsg, wParam, lParam);\r
48 }\r
49 \r
50 BOOL CTCPClientDlg::OnCommand(WPARAM wParam, LPARAM lParam)\r
51 {\r
52         // Respond to the various dialog buttons\r
53 \r
54         UNREFERENCED_PARAMETER(lParam);\r
55 \r
56         switch (LOWORD(wParam))\r
57     {\r
58         case IDC_BUTTON_SEND2:\r
59                 Send();\r
60                 return TRUE;\r
61         }\r
62 \r
63         return FALSE;\r
64 }\r
65 \r
66 BOOL CTCPClientDlg::OnInitDialog()\r
67 {\r
68         SetForegroundWindow();\r
69 \r
70         m_EditSend.AttachDlgItem(IDC_EDIT_SEND2, this);\r
71         m_EditReceive.AttachDlgItem(IDC_EDIT_RECEIVE2, this);\r
72         m_ButtonSend.AttachDlgItem(IDC_BUTTON_SEND2, this);\r
73 \r
74         return TRUE;\r
75 }\r
76 \r
77 void CTCPClientDlg::Receive()\r
78 {\r
79         std::vector<TCHAR> vTChar( 1025, _T('\0') );\r
80         TCHAR* buf = &vTChar.front();   // TChar array with 1025 elements initialised to _T('\0')\r
81         m_pSocket->Receive(buf, 1024, 0);\r
82         Append(IDC_EDIT_RECEIVE2, buf);\r
83 }\r
84 \r
85 void CTCPClientDlg::Send()\r
86 {\r
87         CString sSend = m_EditSend.GetWindowText();\r
88         m_pSocket->Send(sSend, lstrlen(sSend), 0);\r
89 }\r
90 \r
91 \r
92 \r
93 /////////////////////////////////////////////\r
94 // Definitions for the CSvrDialog class\r
95 CSvrDialog::CSvrDialog(UINT nResID, CWnd* pParent) : CDialog(nResID, pParent),\r
96               m_bServerStarted(FALSE), m_SocketType(SOCK_STREAM)\r
97 {\r
98         // Add support for the IP Address control\r
99         // It requires Win95 with IE4 intergrated or a later version of Windows OS.\r
100         LoadCommonControlsEx();\r
101 }\r
102 \r
103 CSvrDialog::~CSvrDialog()\r
104 {\r
105         StopServer();\r
106 }\r
107 \r
108 void CSvrDialog::Append(int nID, LPCTSTR buf)\r
109 {\r
110         // This function appends some text to an edit control\r
111 \r
112         // Append Line Feed\r
113         int ndx = (int)SendDlgItemMessage(nID, WM_GETTEXTLENGTH, 0, 0);\r
114         if (ndx)\r
115         {\r
116 \r
117                 SendDlgItemMessage(nID, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);\r
118                 SendDlgItemMessage(nID, EM_REPLACESEL, 0, (LPARAM) (_T( "\r\n")));\r
119         }\r
120 \r
121         // Append text\r
122         ndx = (int)SendDlgItemMessage(nID, WM_GETTEXTLENGTH, 0, 0);\r
123         SendDlgItemMessage(nID, EM_SETSEL, (WPARAM)ndx, (LPARAM)ndx);\r
124         SendDlgItemMessage(nID, EM_REPLACESEL, 0, (LPARAM) buf);\r
125 }\r
126 \r
127 INT_PTR CSvrDialog::DialogProc(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
128 {\r
129         // respond to the user defined message posted to the dialog\r
130         switch (uMsg)\r
131         {\r
132         case USER_ACCEPT:\r
133                 OnSocketAccept();\r
134                 break;\r
135         case USER_DISCONNECT:\r
136                 OnSocketDisconnect((CServerSocket*)wParam);\r
137                 break;\r
138         case USER_RECEIVE:\r
139                 OnSocketReceive((CServerSocket*)wParam);\r
140                 break;\r
141         case WM_DESTROY:\r
142                 PostQuitMessage(0);\r
143                 break;\r
144         }\r
145 \r
146         // Pass unhandled messages on to parent DialogProc\r
147         return DialogProcDefault(uMsg, wParam, lParam);\r
148 }\r
149 \r
150 void CSvrDialog::LoadCommonControlsEx()\r
151 {\r
152         // This function adds support for the IP address control in the dialog.\r
153         HMODULE hComCtl;\r
154 \r
155         try\r
156         {\r
157                 // Load the Common Controls DLL\r
158                 hComCtl = ::LoadLibrary(_T("COMCTL32.DLL"));\r
159                 if (!hComCtl)\r
160                         throw CWinException(_T("Failed to load COMCTL32.DLL"));\r
161 \r
162                 if (GetComCtlVersion() > 470)\r
163                 {\r
164                         // Declare a pointer to the InItCommonControlsEx function\r
165                         typedef BOOL WINAPI INIT_EX(INITCOMMONCONTROLSEX*);\r
166                         INIT_EX* pfnInit = (INIT_EX*)::GetProcAddress(hComCtl, "InitCommonControlsEx");\r
167 \r
168                         // Call InitCommonControlsEx\r
169                         INITCOMMONCONTROLSEX InitStruct;\r
170                         InitStruct.dwSize = sizeof(INITCOMMONCONTROLSEX);\r
171                         InitStruct.dwICC = ICC_INTERNET_CLASSES;\r
172                         if((!(*pfnInit)(&InitStruct)))\r
173                                 throw CWinException(_T("InitCommonControlsEx failed"));\r
174                 }\r
175                 else\r
176                 {\r
177                         ::MessageBox(NULL, _T("IP Address Control not supported!"), _T("Error"), MB_OK);\r
178                 }\r
179 \r
180                 ::FreeLibrary(hComCtl);\r
181         }\r
182 \r
183         catch (const CWinException &e)\r
184         {\r
185                 e.what();\r
186                 if (hComCtl)\r
187                         ::FreeLibrary(hComCtl);\r
188         }\r
189 }\r
190 \r
191 void CSvrDialog::OnSocketDisconnect(CServerSocket* pClient)\r
192 {\r
193         // Respond to a socket disconnect notification\r
194         Append(IDC_EDIT_STATUS, _T("Client disconnected"));\r
195 \r
196 \r
197         // Allocate an iterator for our CServerSocket map\r
198         std::map< ServerSocketPtr, TCPClientDlgPtr >::iterator Iter;\r
199 \r
200         for (Iter = m_ConnectedClients.begin(); Iter != m_ConnectedClients.end(); ++Iter)\r
201         {\r
202                 if (Iter->first.get() == pClient)\r
203                         break;\r
204         }\r
205 \r
206         // delete the CServerSocket, and remove its pointer\r
207         if (Iter != m_ConnectedClients.end())\r
208         {\r
209                 m_ConnectedClients.erase(Iter);\r
210         }\r
211 }\r
212 \r
213 BOOL CSvrDialog::OnCommand(WPARAM wParam, LPARAM lParam)\r
214 {\r
215         UNREFERENCED_PARAMETER(lParam);\r
216 \r
217         // Respond to the various dialog buttons\r
218         switch (LOWORD(wParam))\r
219     {\r
220         case IDC_BUTTON_START:\r
221                 OnStartServer();\r
222                 return TRUE;\r
223         case IDC_BUTTON_SEND:\r
224                 OnSend();\r
225                 return TRUE;\r
226     } //switch (LOWORD(wParam))\r
227 \r
228         return FALSE;\r
229 }\r
230 \r
231 BOOL CSvrDialog::OnInitDialog()\r
232 {\r
233         // Set the Icon\r
234         SetIconLarge( IDW_MAIN );\r
235         SetIconSmall( IDW_MAIN );\r
236 \r
237         // reposition dialog\r
238         CRect rc = GetWindowRect();\r
239         MoveWindow( rc.left-14, rc.top-14, rc.Width(), rc.Height(), TRUE );\r
240 \r
241         // Attach CWnd objects to the dialog's children\r
242         m_IP4Address.AttachDlgItem( IDC_IPADDRESS, this );\r
243         m_EditIP6Address.AttachDlgItem( IDC_EDIT_IPV6ADDRESS, this );\r
244         m_EditStatus.AttachDlgItem( IDC_EDIT_STATUS, this );\r
245         m_EditPort.AttachDlgItem( IDC_EDIT_PORT, this );\r
246         m_EditSend.AttachDlgItem( IDC_EDIT_SEND, this );\r
247         m_EditReceive.AttachDlgItem( IDC_EDIT_RECEIVE, this );\r
248         m_ButtonStart.AttachDlgItem( IDC_BUTTON_START, this );\r
249         m_ButtonSend.AttachDlgItem( IDC_BUTTON_SEND, this );\r
250         m_RadioIP4.AttachDlgItem( IDC_RADIO_IPV4, this );\r
251         m_RadioIP6.AttachDlgItem( IDC_RADIO_IPV6, this );\r
252         m_RadioTCP.AttachDlgItem( IDC_RADIO_TCP, this );\r
253         m_RadioUDP.AttachDlgItem( IDC_RADIO_UDP, this );\r
254 \r
255         // Set the initial state of the dialog\r
256         m_EditIP6Address.SetWindowText( _T("0000:0000:0000:0000:0000:0000:0000:0001") );\r
257         m_RadioIP4.SendMessage( BM_SETCHECK, BST_CHECKED, 0 );\r
258         m_IP4Address.SendMessage( IPM_SETADDRESS, 0, MAKEIPADDRESS(127, 0, 0, 1) );\r
259         m_EditStatus.SetWindowText( _T("Server Stopped") );\r
260         m_EditPort.SetWindowText( _T("3000") );\r
261         m_RadioTCP.SendMessage( BM_SETCHECK, BST_CHECKED, 0 );\r
262         if (!m_MainSocket.IsIPV6Supported())\r
263         {\r
264                 m_RadioIP6.EnableWindow(FALSE);\r
265                 m_EditIP6Address.EnableWindow(FALSE);\r
266         }\r
267 \r
268         return true;\r
269 }\r
270 \r
271 void CSvrDialog::OnStartServer()\r
272 {\r
273         // Respond to the Start/Stop Button press\r
274         TRACE( _T("Start/Stop Button Pressed\n") );\r
275 \r
276         if (!m_bServerStarted)\r
277         {\r
278                 // Attempt to start the server\r
279                 if (!StartServer())\r
280                         return;\r
281 \r
282                 // Update the dialog\r
283                 m_ButtonStart.SetWindowText( _T("Stop Server") );\r
284                 m_IP4Address.EnableWindow(FALSE);\r
285                 m_EditIP6Address.EnableWindow(FALSE);\r
286                 m_EditPort.EnableWindow(FALSE);\r
287                 m_RadioIP4.EnableWindow(FALSE);\r
288                 m_RadioIP6.EnableWindow(FALSE);\r
289                 m_RadioTCP.EnableWindow(FALSE);\r
290                 m_RadioUDP.EnableWindow(FALSE);\r
291 \r
292 \r
293                 if (m_SocketType == SOCK_STREAM)\r
294                 {\r
295                         Append(IDC_EDIT_STATUS, _T("TCP Server Started"));\r
296                         Append(IDC_EDIT_STATUS, _T("Waiting for client ..."));\r
297                 }\r
298                 else\r
299                 {\r
300                         Append(IDC_EDIT_STATUS, _T("UDP Server Started"));\r
301                         Append(IDC_EDIT_STATUS, _T("Waiting for client data"));\r
302                 }\r
303         }\r
304         else\r
305         {\r
306                 StopServer();\r
307 \r
308                 // Update the dialog\r
309                 Append(IDC_EDIT_STATUS, _T("Server Stopped"));\r
310                 m_ButtonStart.SetWindowText( _T("Start Server") );\r
311                 m_IP4Address.EnableWindow(TRUE);\r
312                 m_EditPort.EnableWindow(TRUE);\r
313                 m_RadioIP4.EnableWindow(TRUE);\r
314                 m_RadioTCP.EnableWindow(TRUE);\r
315                 m_RadioUDP.EnableWindow(TRUE);\r
316                 m_ButtonSend.EnableWindow(FALSE);\r
317                 m_EditSend.EnableWindow(FALSE);\r
318                 if (m_MainSocket.IsIPV6Supported())\r
319                 {\r
320                         m_RadioIP6.EnableWindow(TRUE);\r
321                         m_EditIP6Address.EnableWindow(TRUE);\r
322                 }\r
323         }\r
324         m_bServerStarted = !m_bServerStarted;\r
325 }\r
326 \r
327 void CSvrDialog::OnSend()\r
328 {\r
329         // Responds to the send button\r
330 \r
331         switch(m_SocketType)\r
332         {\r
333                 case SOCK_STREAM:\r
334                         // TCP connections have a seperate chat dialog for sending/receiving data\r
335                         break;\r
336                 case SOCK_DGRAM:\r
337                         {\r
338                                 CString sSend = m_EditSend.GetWindowText();\r
339                                 m_MainSocket.SendTo(sSend, lstrlen(sSend), 0, (LPSOCKADDR)&m_saUDPClient, sizeof(m_saUDPClient));\r
340                         }\r
341                         break;\r
342         }\r
343 }\r
344 \r
345 void CSvrDialog::OnSocketAccept()\r
346 {\r
347         // Accept the connection from the client\r
348         ServerSocketPtr pClient = new CServerSocket;\r
349         m_MainSocket.Accept(*pClient, NULL, NULL);\r
350         if (INVALID_SOCKET == m_MainSocket.GetSocket())\r
351         {\r
352                 TRACE(_T("Failed to accept connection from client\n"));\r
353                 TRACE(m_MainSocket.GetLastError());\r
354                 return;\r
355         }\r
356 \r
357         pClient->StartEvents();\r
358 \r
359         // Create the new chat dialog\r
360         TCPClientDlgPtr pDialog = new CTCPClientDlg(IDD_CHAT, this);\r
361         pDialog->m_pSocket = pClient;\r
362         pDialog->DoModeless();\r
363 \r
364         // Reposition the chat dialog\r
365         CRect rc = pDialog->GetWindowRect();\r
366         int offset = 4 * ((int)m_ConnectedClients.size() - 1);\r
367         pDialog->MoveWindow(rc.left + offset, rc.top + offset + 80, rc.Width(), rc.Height(), TRUE);\r
368         pDialog->ShowWindow();\r
369 \r
370         // Add the socket and dialog to the map\r
371         m_ConnectedClients.insert(std::make_pair(pClient, pDialog));\r
372 \r
373         // Update the dialog\r
374         Append(IDC_EDIT_STATUS, _T("Client Connected"));\r
375 }\r
376 \r
377 void CSvrDialog::OnSocketReceive(CServerSocket* pClient)\r
378 {\r
379         std::vector<TCHAR> vTChar(1025, _T('\0'));\r
380         TCHAR* bufArray = &vTChar.front(); // TCHAR array with 1025 elements\r
381 \r
382         switch (m_SocketType)\r
383         {\r
384         case SOCK_STREAM:\r
385                 {\r
386                         // Pass this on to the TCP chat dialog\r
387                         std::map< ServerSocketPtr, TCPClientDlgPtr >::iterator Iter;\r
388 \r
389                         for (Iter = m_ConnectedClients.begin(); Iter != m_ConnectedClients.end(); ++Iter)\r
390                         {\r
391                                 if (Iter->first.get() == pClient)\r
392                                 break;\r
393                         }\r
394 \r
395                         if (Iter !=  m_ConnectedClients.end() )\r
396                                 Iter->second->Receive();\r
397                 }\r
398                 break;\r
399         case SOCK_DGRAM:\r
400                 {\r
401                         int addrlen = sizeof(m_saUDPClient);\r
402                         m_MainSocket.ReceiveFrom(bufArray, 1024, 0, (LPSOCKADDR)&m_saUDPClient, &addrlen);\r
403                         TRACE(_T("[Received:] ")); TRACE(bufArray); TRACE(_T("\n"));\r
404                         m_ButtonSend.EnableWindow(TRUE);\r
405                         m_EditSend.EnableWindow(TRUE);\r
406                         SendMessage( WM_NEXTDLGCTL, (WPARAM)GetDlgItem(IDC_EDIT_SEND), TRUE );\r
407                 }\r
408                 break;\r
409         }\r
410         Append(IDC_EDIT_RECEIVE, bufArray);\r
411 }\r
412 \r
413 BOOL CSvrDialog::StartServer()\r
414 {\r
415         LRESULT lr = m_RadioTCP.SendMessage( BM_GETCHECK, 0, 0 );\r
416         m_SocketType = (lr == BST_CHECKED)? SOCK_STREAM : SOCK_DGRAM ;\r
417 \r
418         // Create the main socket\r
419         lr = m_RadioIP4.SendMessage( BM_GETCHECK, 0, 0 );\r
420         int IPfamily = (lr == BST_CHECKED)? PF_INET : PF_INET6 ;\r
421         if (!m_MainSocket.Create(IPfamily, m_SocketType))\r
422         {\r
423                 Append(IDC_EDIT_STATUS, _T("Create Socket Failed"));\r
424                 Append(IDC_EDIT_STATUS, m_MainSocket.GetLastError());\r
425                 return FALSE;\r
426         }\r
427 \r
428         // Retrieve the IP Address\r
429         CString strAddr;\r
430         if (PF_INET6 == IPfamily)\r
431         {\r
432                 strAddr = m_EditIP6Address.GetWindowText();\r
433         }\r
434         else\r
435         {\r
436                 DWORD dwAddr = 0;\r
437                 m_IP4Address.SendMessage( IPM_GETADDRESS, 0, (LPARAM) (LPDWORD) &dwAddr );\r
438                 in_addr addr = {0};\r
439                 addr.S_un.S_addr = htonl(dwAddr);\r
440                 strAddr = A2T( inet_ntoa(addr) );\r
441         }\r
442 \r
443         // Retrieve the local port number\r
444         CString strPort = m_EditPort.GetWindowText();\r
445 \r
446         // Bind to the socket\r
447         Append(IDC_EDIT_STATUS, _T("Binding to socket"));\r
448         CString str;\r
449         str.Format( _T("Addr %s, Port %s, type %s"), strAddr.c_str(), strPort.c_str(), (m_SocketType == SOCK_STREAM)?_T("TCP"):_T("UDP") );\r
450         Append(IDC_EDIT_STATUS, str);\r
451 \r
452         int RetVal = m_MainSocket.Bind( strAddr, strPort );\r
453         if ( RetVal != 0 )\r
454         {\r
455                 Append(IDC_EDIT_STATUS, _T("Bind failed"));\r
456                 Append(IDC_EDIT_STATUS, m_MainSocket.GetLastError());\r
457                 return FALSE;\r
458         }\r
459 \r
460         if (m_SocketType == SOCK_STREAM)\r
461         {\r
462                 // Listen for connections from clients (TCP server only)\r
463                 RetVal = m_MainSocket.Listen();\r
464                 if      ( SOCKET_ERROR == RetVal )\r
465                 {\r
466                         Append(IDC_EDIT_STATUS, _T("Error listening on socket"));\r
467                         Append(IDC_EDIT_STATUS, m_MainSocket.GetLastError());\r
468                         return FALSE;\r
469                 }\r
470         }\r
471 \r
472         m_MainSocket.StartEvents();\r
473 \r
474         return TRUE;\r
475 }\r
476 \r
477 void CSvrDialog::StopServer()\r
478 {\r
479         m_MainSocket.Disconnect();\r
480         m_ConnectedClients.clear();\r
481 }\r

UCC git Repository :: git.ucc.asn.au