Click here to Skip to main content
15,886,799 members
Articles / Desktop Programming / MFC

CAsyncSocketEx - Replacement for CAsyncSocket with proxy and SSL support

Rate me:
Please Sign up or sign in to vote.
4.90/5 (36 votes)
5 Apr 20036 min read 503.5K   15.6K   136  
CAsyncSocketEx is an MFC-less replacement for CAsyncSocket which does also offer a flexible layer system. With the layer class CAsyncProxySocketLayer, you can connect through proxy servers.
// CAsyncSocketExDemoDlg.cpp : Implementierungsdatei
//

#include "stdafx.h"
#include "CAsyncSocketExDemo.h"
#include "CAsyncSocketExDemoDlg.h"
#include "VerifyCertDlg.h"

#include "MySocket.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg-Dialogfeld f�r Anwendungsbefehl "Info"

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialogfelddaten
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// Vom Klassenassistenten generierte �berladungen virtueller Funktionen
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterst�tzung
	//}}AFX_VIRTUAL

// Implementierung
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// Keine Nachrichten-Handler
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCAsyncSocketExDemoDlg Dialogfeld

CCAsyncSocketExDemoDlg::CCAsyncSocketExDemoDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CCAsyncSocketExDemoDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CCAsyncSocketExDemoDlg)
	m_Host = _T("");
	m_nPort = 21;
	m_ProxyPass = _T("");
	m_ProxyHost = _T("");
	m_ProxyUser = _T("");
	m_bUseAuth = FALSE;
	m_nProxyType = -1;
	m_nProxyPort = 0;
	m_bUseSsl = FALSE;
	//}}AFX_DATA_INIT
	// Beachten Sie, dass LoadIcon unter Win32 keinen nachfolgenden DestroyIcon-Aufruf ben�tigt
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

CCAsyncSocketExDemoDlg::~CCAsyncSocketExDemoDlg()
{
	for (t_HashList::iterator iter = m_SslTrustedCertHashList.begin(); iter != m_SslTrustedCertHashList.end(); iter++)
		delete [] *iter;
}

void CCAsyncSocketExDemoDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CCAsyncSocketExDemoDlg)
	DDX_Control(pDX, IDC_RESPONSE, m_cResponse);
	DDX_Text(pDX, IDC_HOST, m_Host);
	DDX_Text(pDX, IDC_PORT, m_nPort);
	DDV_MinMaxInt(pDX, m_nPort, 1, 65535);
	DDX_Text(pDX, IDC_PPASS, m_ProxyPass);
	DDV_MaxChars(pDX, m_ProxyPass, 255);
	DDX_Text(pDX, IDC_PHOST, m_ProxyHost);
	DDX_Text(pDX, IDC_PUSER, m_ProxyUser);
	DDV_MaxChars(pDX, m_ProxyUser, 255);
	DDX_Check(pDX, IDC_USEAUTH, m_bUseAuth);
	DDX_Radio(pDX, IDC_RADIO1, m_nProxyType);
	DDX_Text(pDX, IDC_PPORT, m_nProxyPort);
	DDX_Check(pDX, IDC_USESSL, m_bUseSsl);
	if (m_nProxyType)
		DDV_MinMaxInt(pDX, m_nProxyPort, 1, 65535);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CCAsyncSocketExDemoDlg, CDialog)
	//{{AFX_MSG_MAP(CCAsyncSocketExDemoDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDOK, OnConnect)
	ON_WM_CLOSE()
	ON_MESSAGE(WM_USER, OnVerifyCert)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCAsyncSocketExDemoDlg Nachrichten-Handler

BOOL CCAsyncSocketExDemoDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Hinzuf�gen des Men�befehls "Info..." zum Systemmen�.

	// IDM_ABOUTBOX muss sich im Bereich der Systembefehle befinden.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Symbol f�r dieses Dialogfeld festlegen. Wird automatisch erledigt
	//  wenn das Hauptfenster der Anwendung kein Dialogfeld ist
	SetIcon(m_hIcon, TRUE);			// Gro�es Symbol verwenden
	SetIcon(m_hIcon, FALSE);		// Kleines Symbol verwenden

	// ZU ERLEDIGEN: Hier zus�tzliche Initialisierung einf�gen
	m_pMySocket=0;
	m_nProxyType=0;
	UpdateData(FALSE);

	return TRUE;  // Geben Sie TRUE zur�ck, au�er ein Steuerelement soll den Fokus erhalten
}

void CCAsyncSocketExDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// Wollen Sie Ihrem Dialogfeld eine Schaltfl�che "Minimieren" hinzuf�gen, ben�tigen Sie
//  den nachstehenden Code, um das Symbol zu zeichnen. F�r MFC-Anwendungen, die das
//  Dokument/Ansicht-Modell verwenden, wird dies automatisch f�r Sie erledigt.

void CCAsyncSocketExDemoDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // Ger�tekontext f�r Zeichnen

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Symbol in Client-Rechteck zentrieren
		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;

		// Symbol zeichnen
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// Die Systemaufrufe fragen den Cursorform ab, die angezeigt werden soll, w�hrend der Benutzer
//  das zum Symbol verkleinerte Fenster mit der Maus zieht.
HCURSOR CCAsyncSocketExDemoDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CCAsyncSocketExDemoDlg::OnConnect()
{
	//Validate all input fields
	if (!UpdateData(TRUE))
		return;
	if (m_nProxyType!=0)
	{
		if (m_ProxyHost=="")
		{
			AfxMessageBox("Please enter the proxy host!");
			return;
		}
		if (m_nProxyPort<1 || m_nProxyPort>65535)
		{
			AfxMessageBox("Please enter a valid port for the proxy!");
			return;
		}
	}
	if (((m_nProxyType==3) || (m_nProxyType==4)) && m_bUseAuth)
	{
		if (m_ProxyUser=="")
		{
			AfxMessageBox("Please enter the username for the proxy server!");
			return;
		}
		if (m_ProxyPass=="")
		{
			AfxMessageBox("Please enter the password for the proxy server!");
			return;
		}
	}
	if (m_Host=="")
	{
		AfxMessageBox("Please enter a server!");
		return;
	}
	if (m_nPort<1 || m_nPort>65535)
	{
		AfxMessageBox("Please enter a valid port for the server!");
		return;
	}

	//If connected, close old connection
	if (m_pMySocket)
		delete m_pMySocket;
	m_cResponse.SetWindowText("");
	m_pMySocket=new CMySocket(&m_cResponse, &m_SslTrustedCertHashList);

	if (m_bUseSsl)
		m_pMySocket->AddLayer(m_pMySocket->m_pSslLayer);

	//Set the type of the proxy
	if (m_nProxyType)
	{
		if (m_nProxyType==1)
			m_pMySocket->m_pProxyLayer->SetProxy(PROXYTYPE_SOCKS4,m_ProxyHost,m_nProxyPort);
		else if (m_nProxyType==2)
			m_pMySocket->m_pProxyLayer->SetProxy(PROXYTYPE_SOCKS4A,m_ProxyHost,m_nProxyPort);
		else if (m_nProxyType==3 && !m_bUseAuth)
			m_pMySocket->m_pProxyLayer->SetProxy(PROXYTYPE_SOCKS5,m_ProxyHost,m_nProxyPort);
		else if (m_nProxyType==3 && m_bUseAuth)
			m_pMySocket->m_pProxyLayer->SetProxy(PROXYTYPE_SOCKS5,m_ProxyHost,m_nProxyPort,m_ProxyUser,m_ProxyPass);
		else if (m_nProxyType==4 && !m_bUseAuth)
			m_pMySocket->m_pProxyLayer->SetProxy(PROXYTYPE_HTTP11,m_ProxyHost,m_nProxyPort);
		else if (m_nProxyType==4 && m_bUseAuth)
			m_pMySocket->m_pProxyLayer->SetProxy(PROXYTYPE_HTTP11,m_ProxyHost,m_nProxyPort,m_ProxyUser,m_ProxyPass);
		else
			m_pMySocket->m_pProxyLayer->SetProxy(PROXYTYPE_NOPROXY);
		VERIFY(m_pMySocket->AddLayer(m_pMySocket->m_pProxyLayer));
	}

	m_pMySocket->Create();

	if (m_bUseSsl)
		m_pMySocket->m_pSslLayer->InitClientSSL();

	//Connect
	BOOL res=m_pMySocket->Connect(m_Host,m_nPort);
	if (!res)
		if (GetLastError()!=WSAEWOULDBLOCK)
		{
			if (m_nProxyType)
				AddStringToLog("Error: Can't connect to proxy server.");
			else
				AddStringToLog("Error: Can't connect to server.");
			return;
		}
	AddStringToLog("Connecting, please wait...");
}

void CCAsyncSocketExDemoDlg::OnClose()
{
	if (m_pMySocket)
		delete m_pMySocket;
	m_pMySocket=0;
	CDialog::OnClose();
}

void CCAsyncSocketExDemoDlg::AddStringToLog(LPCTSTR pszString)
{
	CString str;
	m_cResponse.GetWindowText(str);
	str+=pszString;
	str+=_T("\r\n");
	m_cResponse.SetWindowText(str);
}

LRESULT CCAsyncSocketExDemoDlg::OnVerifyCert(WPARAM wParam, LPARAM lParam)
{
	t_SslCertData *pData = reinterpret_cast<t_SslCertData*>(wParam);
	if (!pData)
		return 0;

	CVerifyCertDlg dlg;
	dlg.m_CertData = *pData;
	int res = dlg.DoModal();
	if (res == IDOK)
	{
		if (dlg.m_bAlways)
			m_pMySocket->AddSslCertHashToTrustedList(pData->hash);
		m_pMySocket->m_pSslLayer->SetNotifyReply(pData->priv_data, SSL_VERIFY_CERT, 1);
	}
	else 
		m_pMySocket->m_pSslLayer->SetNotifyReply(pData->priv_data, SSL_VERIFY_CERT, 0);
	delete pData;


	return 0;
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions