|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
// MessageWatchDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MessageWatch.h"
#include "MessageWatchDlg.h"
#include "messagemgr.h"
#include "tier1/strtools.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__; #endif
#define WM_STARTIDLE (WM_USER + 565)
// --------------------------------------------------------------------------- //
// CSender.
// --------------------------------------------------------------------------- //
CSender::CSender() { m_pSocket = NULL; m_pConsoleWnd = NULL; }
CSender::~CSender() { if ( m_pSocket ) m_pSocket->Release(); if ( m_pConsoleWnd ) m_pConsoleWnd->Release(); }
/////////////////////////////////////////////////////////////////////////////
// CMessageWatchDlg dialog
CMessageWatchDlg::CMessageWatchDlg(CWnd* pParent /*=NULL*/) : CDialog(CMessageWatchDlg::IDD, pParent) { //{{AFX_DATA_INIT(CMessageWatchDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pListenSocket = NULL; }
CMessageWatchDlg::~CMessageWatchDlg() { // destroy the sender objects.
if ( m_pListenSocket ) m_pListenSocket->Release(); }
void CMessageWatchDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMessageWatchDlg)
DDX_Control(pDX, IDC_MACHINES, m_Machines); //}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMessageWatchDlg, CDialog) //{{AFX_MSG_MAP(CMessageWatchDlg)
ON_MESSAGE(WM_STARTIDLE, OnStartIdle) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_LBN_DBLCLK(IDC_MACHINES, OnDblclkMachines) ON_BN_CLICKED(IDSHOWALL, OnShowall) ON_BN_CLICKED(IDHIDEALL, OnHideall) //}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMessageWatchDlg message handlers
BOOL CMessageWatchDlg::OnInitDialog() { CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// Setup our listen socket and thread.
m_pListenSocket = CreateIPSocket(); m_pListenSocket->BindToAny( MSGMGR_BROADCAST_PORT );
m_cWinIdle.StartIdle( GetSafeHwnd(), WM_STARTIDLE, 0, 0, 100 ); m_cWinIdle.NextIdle(); return TRUE; // return TRUE unless you set the focus to a control
}
LONG CMessageWatchDlg::OnStartIdle( UINT, LONG ) { MSG msg; if (!PeekMessage(&msg, GetSafeHwnd(), 0,0, PM_NOREMOVE)) OnIdle(); m_cWinIdle.NextIdle(); return 0; }
void CMessageWatchDlg::OnIdle() { // Kill dead connections.
int iNext; for ( int iSender=m_Senders.Head(); iSender != m_Senders.InvalidIndex(); iSender = iNext ) { iNext = m_Senders.Next( iSender );
CSender *pSender = m_Senders[iSender]; if ( pSender->m_pSocket && !pSender->m_pSocket->IsConnected() ) { // Just release the socket so the text stays there.
pSender->m_pSocket->Release(); pSender->m_pSocket = NULL; } }
// Look for new connections.
while ( 1 ) { CIPAddr ipFrom; char data[16]; int len = m_pListenSocket->RecvFrom( data, sizeof( data ), &ipFrom ); if ( len == -1 ) break;
if ( data[0] == MSGMGR_PACKETID_ANNOUNCE_PRESENCE && *((int*)&data[1]) == MSGMGR_VERSION ) { int iPort = *((int*)&data[5]); // See if we have a machine with this info yet.
CIPAddr connectAddr = ipFrom; connectAddr.port = iPort;
// NOTE: we'll accept connections from machines we were connected to earlier but
// lost the connection to.
CSender *pSender = FindSenderByAddr( ipFrom.ip ); if ( !pSender || !pSender->m_pSocket ) { // 'nitiate the connection.
ITCPSocket *pNew = CreateTCPSocket(); if ( pNew->BindToAny( 0 ) && TCPSocket_Connect( pNew, &connectAddr, 1000 ) ) { char nameStr[256]; char title[512]; if ( !ConvertIPAddrToString( &ipFrom, nameStr, sizeof( nameStr ) ) ) Q_snprintf( nameStr, sizeof( nameStr ), "%d.%d.%d.%d", ipFrom.ip[0], ipFrom.ip[1], ipFrom.ip[2], ipFrom.ip[3] ); Q_snprintf( title, sizeof( title ), "%s:%d", nameStr, iPort );
// If the sender didn't exist yet, add a new one.
if ( !pSender ) { pSender = new CSender; IConsoleWnd *pWnd = CreateConsoleWnd( AfxGetInstanceHandle(), IDD_OUTPUT, IDC_DEBUG_OUTPUT, false );
pSender->m_pConsoleWnd = pWnd; pWnd->SetTitle( title ); Q_strncpy( pSender->m_Name, title, sizeof( pSender->m_Name ) ); m_Senders.AddToTail( pSender ); m_Machines.AddString( pSender->m_Name ); }
pSender->m_Addr = connectAddr; pSender->m_pSocket = pNew; } else { pNew->Release(); } } } }
// Read input from our current connections.
FOR_EACH_LL( m_Senders, i ) { CSender *pSender = m_Senders[i];
while ( 1 ) { if ( !pSender->m_pSocket ) break;
CUtlVector<unsigned char> data; if ( !pSender->m_pSocket->Recv( data ) ) break;
if ( data[0] == MSGMGR_PACKETID_MSG ) { char *pMsg = (char*)&data[1]; pSender->m_pConsoleWnd->PrintToConsole( pMsg ); OutputDebugString( pMsg ); } } } }
void CMessageWatchDlg::OnDestroy() { // Stop the idling thread
m_cWinIdle.EndIdle(); CDialog::OnDestroy(); }
CSender* CMessageWatchDlg::FindSenderByAddr( const unsigned char ip[4] ) { FOR_EACH_LL( m_Senders, i ) { if ( memcmp( m_Senders[i]->m_Addr.ip, ip, 4 ) == 0 ) return m_Senders[i]; } return NULL; }
CSender* CMessageWatchDlg::FindSenderByName( const char *pName ) { FOR_EACH_LL( m_Senders, i ) { if ( stricmp( pName, m_Senders[i]->m_Name ) == 0 ) return m_Senders[i]; } return NULL; }
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CMessageWatchDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } }
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CMessageWatchDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; }
void CMessageWatchDlg::OnDblclkMachines() { int index = m_Machines.GetCurSel(); if ( index != LB_ERR ) { CString str; m_Machines.GetText( index, str );
CSender *pSender = FindSenderByName( str ); if ( pSender ) pSender->m_pConsoleWnd->SetVisible( true ); } }
void CMessageWatchDlg::OnShowall() { FOR_EACH_LL( m_Senders, i ) { m_Senders[i]->m_pConsoleWnd->SetVisible( true ); } }
void CMessageWatchDlg::OnHideall() { FOR_EACH_LL( m_Senders, i ) { m_Senders[i]->m_pConsoleWnd->SetVisible( false ); } }
|