Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

324 lines
7.3 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // MessageWatchDlg.cpp : implementation file
  9. //
  10. #include "stdafx.h"
  11. #include "MessageWatch.h"
  12. #include "MessageWatchDlg.h"
  13. #include "messagemgr.h"
  14. #include "tier1/strtools.h"
  15. #ifdef _DEBUG
  16. #define new DEBUG_NEW
  17. #undef THIS_FILE
  18. static char THIS_FILE[] = __FILE__;
  19. #endif
  20. #define WM_STARTIDLE (WM_USER + 565)
  21. // --------------------------------------------------------------------------- //
  22. // CSender.
  23. // --------------------------------------------------------------------------- //
  24. CSender::CSender()
  25. {
  26. m_pSocket = NULL;
  27. m_pConsoleWnd = NULL;
  28. }
  29. CSender::~CSender()
  30. {
  31. if ( m_pSocket )
  32. m_pSocket->Release();
  33. if ( m_pConsoleWnd )
  34. m_pConsoleWnd->Release();
  35. }
  36. /////////////////////////////////////////////////////////////////////////////
  37. // CMessageWatchDlg dialog
  38. CMessageWatchDlg::CMessageWatchDlg(CWnd* pParent /*=NULL*/)
  39. : CDialog(CMessageWatchDlg::IDD, pParent)
  40. {
  41. //{{AFX_DATA_INIT(CMessageWatchDlg)
  42. // NOTE: the ClassWizard will add member initialization here
  43. //}}AFX_DATA_INIT
  44. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  45. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  46. m_pListenSocket = NULL;
  47. }
  48. CMessageWatchDlg::~CMessageWatchDlg()
  49. {
  50. // destroy the sender objects.
  51. if ( m_pListenSocket )
  52. m_pListenSocket->Release();
  53. }
  54. void CMessageWatchDlg::DoDataExchange(CDataExchange* pDX)
  55. {
  56. CDialog::DoDataExchange(pDX);
  57. //{{AFX_DATA_MAP(CMessageWatchDlg)
  58. DDX_Control(pDX, IDC_MACHINES, m_Machines);
  59. //}}AFX_DATA_MAP
  60. }
  61. BEGIN_MESSAGE_MAP(CMessageWatchDlg, CDialog)
  62. //{{AFX_MSG_MAP(CMessageWatchDlg)
  63. ON_MESSAGE(WM_STARTIDLE, OnStartIdle)
  64. ON_WM_PAINT()
  65. ON_WM_QUERYDRAGICON()
  66. ON_LBN_DBLCLK(IDC_MACHINES, OnDblclkMachines)
  67. ON_BN_CLICKED(IDSHOWALL, OnShowall)
  68. ON_BN_CLICKED(IDHIDEALL, OnHideall)
  69. //}}AFX_MSG_MAP
  70. END_MESSAGE_MAP()
  71. /////////////////////////////////////////////////////////////////////////////
  72. // CMessageWatchDlg message handlers
  73. BOOL CMessageWatchDlg::OnInitDialog()
  74. {
  75. CDialog::OnInitDialog();
  76. // Set the icon for this dialog. The framework does this automatically
  77. // when the application's main window is not a dialog
  78. SetIcon(m_hIcon, TRUE); // Set big icon
  79. SetIcon(m_hIcon, FALSE); // Set small icon
  80. // Setup our listen socket and thread.
  81. m_pListenSocket = CreateIPSocket();
  82. m_pListenSocket->BindToAny( MSGMGR_BROADCAST_PORT );
  83. m_cWinIdle.StartIdle( GetSafeHwnd(), WM_STARTIDLE, 0, 0, 100 );
  84. m_cWinIdle.NextIdle();
  85. return TRUE; // return TRUE unless you set the focus to a control
  86. }
  87. LONG CMessageWatchDlg::OnStartIdle( UINT, LONG )
  88. {
  89. MSG msg;
  90. if (!PeekMessage(&msg, GetSafeHwnd(), 0,0, PM_NOREMOVE))
  91. OnIdle();
  92. m_cWinIdle.NextIdle();
  93. return 0;
  94. }
  95. void CMessageWatchDlg::OnIdle()
  96. {
  97. // Kill dead connections.
  98. int iNext;
  99. for ( int iSender=m_Senders.Head(); iSender != m_Senders.InvalidIndex(); iSender = iNext )
  100. {
  101. iNext = m_Senders.Next( iSender );
  102. CSender *pSender = m_Senders[iSender];
  103. if ( pSender->m_pSocket && !pSender->m_pSocket->IsConnected() )
  104. {
  105. // Just release the socket so the text stays there.
  106. pSender->m_pSocket->Release();
  107. pSender->m_pSocket = NULL;
  108. }
  109. }
  110. // Look for new connections.
  111. while ( 1 )
  112. {
  113. CIPAddr ipFrom;
  114. char data[16];
  115. int len = m_pListenSocket->RecvFrom( data, sizeof( data ), &ipFrom );
  116. if ( len == -1 )
  117. break;
  118. if ( data[0] == MSGMGR_PACKETID_ANNOUNCE_PRESENCE &&
  119. *((int*)&data[1]) == MSGMGR_VERSION )
  120. {
  121. int iPort = *((int*)&data[5]);
  122. // See if we have a machine with this info yet.
  123. CIPAddr connectAddr = ipFrom;
  124. connectAddr.port = iPort;
  125. // NOTE: we'll accept connections from machines we were connected to earlier but
  126. // lost the connection to.
  127. CSender *pSender = FindSenderByAddr( ipFrom.ip );
  128. if ( !pSender || !pSender->m_pSocket )
  129. {
  130. // 'nitiate the connection.
  131. ITCPSocket *pNew = CreateTCPSocket();
  132. if ( pNew->BindToAny( 0 ) && TCPSocket_Connect( pNew, &connectAddr, 1000 ) )
  133. {
  134. char nameStr[256];
  135. char title[512];
  136. if ( !ConvertIPAddrToString( &ipFrom, nameStr, sizeof( nameStr ) ) )
  137. Q_snprintf( nameStr, sizeof( nameStr ), "%d.%d.%d.%d", ipFrom.ip[0], ipFrom.ip[1], ipFrom.ip[2], ipFrom.ip[3] );
  138. Q_snprintf( title, sizeof( title ), "%s:%d", nameStr, iPort );
  139. // If the sender didn't exist yet, add a new one.
  140. if ( !pSender )
  141. {
  142. pSender = new CSender;
  143. IConsoleWnd *pWnd = CreateConsoleWnd(
  144. AfxGetInstanceHandle(),
  145. IDD_OUTPUT,
  146. IDC_DEBUG_OUTPUT,
  147. false
  148. );
  149. pSender->m_pConsoleWnd = pWnd;
  150. pWnd->SetTitle( title );
  151. Q_strncpy( pSender->m_Name, title, sizeof( pSender->m_Name ) );
  152. m_Senders.AddToTail( pSender );
  153. m_Machines.AddString( pSender->m_Name );
  154. }
  155. pSender->m_Addr = connectAddr;
  156. pSender->m_pSocket = pNew;
  157. }
  158. else
  159. {
  160. pNew->Release();
  161. }
  162. }
  163. }
  164. }
  165. // Read input from our current connections.
  166. FOR_EACH_LL( m_Senders, i )
  167. {
  168. CSender *pSender = m_Senders[i];
  169. while ( 1 )
  170. {
  171. if ( !pSender->m_pSocket )
  172. break;
  173. CUtlVector<unsigned char> data;
  174. if ( !pSender->m_pSocket->Recv( data ) )
  175. break;
  176. if ( data[0] == MSGMGR_PACKETID_MSG )
  177. {
  178. char *pMsg = (char*)&data[1];
  179. pSender->m_pConsoleWnd->PrintToConsole( pMsg );
  180. OutputDebugString( pMsg );
  181. }
  182. }
  183. }
  184. }
  185. void CMessageWatchDlg::OnDestroy()
  186. {
  187. // Stop the idling thread
  188. m_cWinIdle.EndIdle();
  189. CDialog::OnDestroy();
  190. }
  191. CSender* CMessageWatchDlg::FindSenderByAddr( const unsigned char ip[4] )
  192. {
  193. FOR_EACH_LL( m_Senders, i )
  194. {
  195. if ( memcmp( m_Senders[i]->m_Addr.ip, ip, 4 ) == 0 )
  196. return m_Senders[i];
  197. }
  198. return NULL;
  199. }
  200. CSender* CMessageWatchDlg::FindSenderByName( const char *pName )
  201. {
  202. FOR_EACH_LL( m_Senders, i )
  203. {
  204. if ( stricmp( pName, m_Senders[i]->m_Name ) == 0 )
  205. return m_Senders[i];
  206. }
  207. return NULL;
  208. }
  209. // If you add a minimize button to your dialog, you will need the code below
  210. // to draw the icon. For MFC applications using the document/view model,
  211. // this is automatically done for you by the framework.
  212. void CMessageWatchDlg::OnPaint()
  213. {
  214. if (IsIconic())
  215. {
  216. CPaintDC dc(this); // device context for painting
  217. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  218. // Center icon in client rectangle
  219. int cxIcon = GetSystemMetrics(SM_CXICON);
  220. int cyIcon = GetSystemMetrics(SM_CYICON);
  221. CRect rect;
  222. GetClientRect(&rect);
  223. int x = (rect.Width() - cxIcon + 1) / 2;
  224. int y = (rect.Height() - cyIcon + 1) / 2;
  225. // Draw the icon
  226. dc.DrawIcon(x, y, m_hIcon);
  227. }
  228. else
  229. {
  230. CDialog::OnPaint();
  231. }
  232. }
  233. // The system calls this to obtain the cursor to display while the user drags
  234. // the minimized window.
  235. HCURSOR CMessageWatchDlg::OnQueryDragIcon()
  236. {
  237. return (HCURSOR) m_hIcon;
  238. }
  239. void CMessageWatchDlg::OnDblclkMachines()
  240. {
  241. int index = m_Machines.GetCurSel();
  242. if ( index != LB_ERR )
  243. {
  244. CString str;
  245. m_Machines.GetText( index, str );
  246. CSender *pSender = FindSenderByName( str );
  247. if ( pSender )
  248. pSender->m_pConsoleWnd->SetVisible( true );
  249. }
  250. }
  251. void CMessageWatchDlg::OnShowall()
  252. {
  253. FOR_EACH_LL( m_Senders, i )
  254. {
  255. m_Senders[i]->m_pConsoleWnd->SetVisible( true );
  256. }
  257. }
  258. void CMessageWatchDlg::OnHideall()
  259. {
  260. FOR_EACH_LL( m_Senders, i )
  261. {
  262. m_Senders[i]->m_pConsoleWnd->SetVisible( false );
  263. }
  264. }