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
324 lines
7.3 KiB
//========= 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 ); |
|
} |
|
}
|
|
|