source-engine/utils/vmpi/testapps/MessageWatch/MessageWatchDlg.cpp
FluorescentCIAAfricanAmerican 3bf9df6b27 1
2020-04-22 12:56:21 -04:00

325 lines
7.3 KiB
C++

//========= 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 );
}
}