⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socmfc.cpp

📁 MiniCA V2.0版本源码。《小型CA系统V2.1含源码》发表以来
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
Module : SocMFC.cpp
Purpose: Implementation for an MFC wrapper class for sockets
Created: PJN / 05-08-1998
History: 03-03-2003 1. Addition of a number of preprocessor defines, namely W3MFC_EXT_CLASS, 
                    THRDPOOL_EXT_CLASS and SOCKMFC_EXT_CLASS. This allows the classes to easily 
                    be added and exported from a MFC extension dll.
                    2. Now implements support for connecting via Socks 4 and Socks 5 proxies
         21-09-2003 1. Now supports UDP sockets.
                    2. Now supports UDP relaying via Socks 5 proxy.
         26-09-2003 1. Now supports connection via HTTP proxies which support the CONNECT verb
         13-01-2004 1. Used newer form of #pragma pack to avoid problems with non standard 
                    packing sizes.
         25-10-2004 1. Updated to compile cleanly when Detect 64 bit issues and Force conformance 
                    in for loop options are enabled in Visual Studio .NET
         29-12-2004 Almost all of the following updates were to match the functionality provided
                    by the MFC CAsyncSocket class but without the overhead of hidden windows and 
                    its async behaviour.
                    1. Now automatically links to Winsock via #pragma comment
                    2. Addition of a GetPeerName method.
                    3. Replaced all calls to ZeroMemory to memset.
                    4. Addtion of a GetSockName method.
                    5. Addition of a SetSockOpt method.
                    6. Addition of a Flags parameter to Receive method.
                    7. Addition of a IOCtl method.
                    8. Optimized the code in Listen.
                    9. Addition of a ReceiveFrom method.
                    10. Addition of a ShutDown method.
                    11. Optimized the code in Close.
                    12. Remove of pszLocalBoundAddress parameter from Connect methods to make it 
                    consistent with CAsyncSocket.
                    13. Addition of a Flags parameter to Send method.
                    14. Optimized code in CWSocket destructor
                    15. Addition of an overloaded Create method which allows all of the socket
                    parameters to be set
                    16. Use of _tcslen has been minimized when NULL string parameters can be passed
                    to various CWSocket methods.
                    17. Change of various parameter names to be consistent with names as used in
                    CAsyncSocket.
         31-01-2005 1. Fixed a bug in CWSocket::Receive where it throws an error when a graceful 
                    disconnect occurs. Now the code only throws an exception if the return value
                    from recv is SOCKET_ERROR
         01-05-2005 1. Send method now uses a const void* parameter.
         21-06-2005 1. Provision of connect methods which allows a timeout to be specified. Please note
                    that if you use a host name in these calls as opposed to an IP address, the DNS
                    lookup is still done using the OS supplied timeout. Only the actual connection
                    to the server is implemented using a timeout after the DNS lookup is done (if it
                    is necessary).

Copyright (c) 2002 - 2005 by PJ Naughter.  (Web: www.naughter.com, Email: pjna@naughter.com)

All rights reserved.

Copyright / Usage Details:

You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise) 
when your product is released in binary form. You are allowed to modify the source code in any way you want 
except you cannot modify the copyright details at the top of each module. If you want to distribute source 
code with your application, then you are only allowed to distribute versions released by the author. This is 
to maintain a single distribution point for the source code. 

*/



/////////////////// Includes //////////////////////////////////////////////////

#include "stdafx.h"
#include "SocMFC.h"
#include "Base64.h"



/////////////////// Macros / Defines //////////////////////////////////////////

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

#ifndef __AFXPRIV_H__
#pragma message("To avoid this message please put afxpriv.h in your PCH (normally stdafx.h)")
#include <afxpriv.h>
#endif

#pragma comment(lib, "wsock32.lib")



///////////////// Implementation //////////////////////////////////////////////

#pragma pack(push, 1)
struct WSOCKET_SOCK4_CONNECT_REQUEST
{
  BYTE    VN;
  BYTE    CD;
  WORD    DSTPORT;
  in_addr DSTIP;
  BYTE    USERID[1];
};

struct WSOCKET_SOCKS4_CONNECT_REPLY
{
  BYTE    VN;
  BYTE    CD;
  WORD    DSTPORT;
  in_addr DSTIP;
};

struct WSOCKET_SOCKS5_IDENTIFIER_PACKET
{
  BYTE VER;
  BYTE NMETHODS;
  BYTE METHODS[255];
};

struct WSOCKET_SOCKS5_METHODSELECTION_MESSAGE
{
  BYTE VER;
  BYTE METHOD;
};

struct WSOCKET_SOCKS5_BASE_REQUEST_DETAILS
{
  BYTE VER;
  BYTE CMD;
  BYTE RSV;
  BYTE ATYP;
};

struct WSOCKET_SOCKS5_IP4_REQUEST_DETAILS
{
  WSOCKET_SOCKS5_BASE_REQUEST_DETAILS Base;
  in_addr                     DST_IP;
  WORD                        DSTPORT;
};

struct WSOCKET_SOCKS5_HOST_DETAILS
{
  BYTE LENGTH;
  BYTE HOST[255];
};

struct WSOCKET_SOCKS5_HOSTNAME_REQUEST_DETAILS
{
  WSOCKET_SOCKS5_BASE_REQUEST_DETAILS Base;
  WSOCKET_SOCKS5_HOST_DETAILS         DST_HOST;
  WORD                                DSTPORT;
};

struct WSOCKET_SOCKS5_USERNAME_AUTHENTICATION_REPLY
{
  BYTE VER;
  BYTE STATUS;
};
#pragma pack(pop)



////////// Exception handling code

void AfxThrowWSocketException(int nError /* = 0 */)
{
	if (nError == 0)
		nError = ::WSAGetLastError();

	CWSocketException* pException = new CWSocketException(nError);

	TRACE(_T("Warning: throwing CWSocketException for error %d\n"), nError);
	THROW(pException);
}

BOOL CWSocketException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError, PUINT pnHelpContext)
{
	ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));

	if (pnHelpContext != NULL)
		*pnHelpContext = 0;

	LPTSTR lpBuffer;
	BOOL bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
			                      NULL,  m_nError, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
			                      (LPTSTR) &lpBuffer, 0, NULL);

	if (bRet == FALSE)
		*pstrError = '\0';
	else
	{
		lstrcpyn(pstrError, lpBuffer, nMaxError);
		bRet = TRUE;

		LocalFree(lpBuffer);
	}

	return bRet;
}

CString CWSocketException::GetErrorMessage()
{
  CString rVal;
  LPTSTR pstrError = rVal.GetBuffer(4096);
  GetErrorMessage(pstrError, 4096, NULL);
  rVal.ReleaseBuffer();
  return rVal;
}

CWSocketException::CWSocketException(int nError)
{
	m_nError = nError;
}

CWSocketException::~CWSocketException()
{
}

IMPLEMENT_DYNAMIC(CWSocketException, CException)

#ifdef _DEBUG
void CWSocketException::Dump(CDumpContext& dc) const
{
	CObject::Dump(dc);

	dc << "m_nError = " << m_nError;
}
#endif



////////// The main class /////////////////////////////////////

CWSocket::CWSocket() : m_hSocket(INVALID_SOCKET)
{
}

CWSocket::~CWSocket()
{
  if (m_hSocket != INVALID_SOCKET)
    Close();
}

void CWSocket::Attach(SOCKET hSocket)
{
  //Validate our parameters
  ASSERT(hSocket != INVALID_SOCKET);

  if (m_hSocket != INVALID_SOCKET)
    Close();

  m_hSocket = hSocket;
}

SOCKET CWSocket::Detach()
{
  SOCKET socket = m_hSocket;
  m_hSocket = INVALID_SOCKET;
  return socket;
}

void CWSocket::GetPeerName(CString& sPeerAddress, UINT& nPeerPort)
{
  //Validate our parameters
  ASSERT(IsCreated()); //must have been created first

	SOCKADDR_IN sockAddr;
	memset(&sockAddr, 0, sizeof(sockAddr));

	int nSockAddrLen = sizeof(sockAddr);
	GetPeerName((SOCKADDR*)&sockAddr, &nSockAddrLen);
	nPeerPort = ntohs(sockAddr.sin_port);
	sPeerAddress = inet_ntoa(sockAddr.sin_addr);
}

void CWSocket::GetSockName(CString& sSocketAddress, UINT& nSocketPort)
{
  //Validate our parameters
  ASSERT(IsCreated()); //must have been created first

	SOCKADDR_IN sockAddr;
	memset(&sockAddr, 0, sizeof(sockAddr));

	int nSockAddrLen = sizeof(sockAddr);
	GetSockName((SOCKADDR*)&sockAddr, &nSockAddrLen);
	nSocketPort = ntohs(sockAddr.sin_port);
	sSocketAddress = inet_ntoa(sockAddr.sin_addr);
}

void CWSocket::GetPeerName(SOCKADDR* lpSockAddr, int* lpSockAddrLen)
{ 
  //Validate our parameters
  ASSERT(IsCreated()); //Must have been created first

  if (getpeername(m_hSocket, lpSockAddr, lpSockAddrLen) == SOCKET_ERROR)
    AfxThrowWSocketException();
}

void CWSocket::GetSockName(SOCKADDR* lpSockAddr, int* lpSockAddrLen)
{ 
  //Validate our parameters
  ASSERT(IsCreated()); //Must have been created first

  if (getsockname(m_hSocket, lpSockAddr, lpSockAddrLen) == SOCKET_ERROR)
    AfxThrowWSocketException();
}

void CWSocket::Accept(CWSocket& connectedSocket, sockaddr_in& clientAddress)
{
  ASSERT(IsCreated());               //must have been created first
  ASSERT(!connectedSocket.IsCreated()); //Must be an unitialized socket

  //Call the SDK accept function  
  int nSize = sizeof(sockaddr_in);
  SOCKET socket = accept(m_hSocket, (sockaddr*) &clientAddress, &nSize);
  if (socket == INVALID_SOCKET)
    AfxThrowWSocketException(); 

  //Wrap the return value up into a C++ instance
  connectedSocket.Attach(socket);
}

void CWSocket::SetSockOpt(int nOptionName, const void* lpOptionValue, int nOptionLen, int nLevel)
{ 
  //Validate our parameters
  ASSERT(IsCreated()); //Must have been created first

  if (setsockopt(m_hSocket, nLevel, nOptionName, (LPCSTR)lpOptionValue, nOptionLen) == SOCKET_ERROR)
    AfxThrowWSocketException();
}

void CWSocket::GetSockOpt(int nOptionName, void* lpOptionValue, int* lpOptionLen, int nLevel)
{ 
  //Validate our parameters
  ASSERT(IsCreated()); //Must have been created first

  if (getsockopt(m_hSocket, nLevel, nOptionName, (LPSTR)lpOptionValue, lpOptionLen) == SOCKET_ERROR)
    AfxThrowWSocketException();
}

void CWSocket::Bind(const SOCKADDR* lpSockAddr, int nSockAddrLen)
{ 
  //Validate our parameters
  ASSERT(IsCreated()); //Must have been created first

  if (bind(m_hSocket, lpSockAddr, nSockAddrLen) == SOCKET_ERROR)
    AfxThrowWSocketException();
}

void CWSocket::Bind(UINT nSocketPort, LPCTSTR lpszSocketAddress)
{
	USES_CONVERSION;

  //Setup the structure used in sdk "bind" calls
  SOCKADDR_IN sockAddr;
  memset(&sockAddr, 0, sizeof(sockAddr));

  sockAddr.sin_family = AF_INET;
  sockAddr.sin_port = htons((u_short)nSocketPort);

  //Do we need to bind to a specific IP address?
  if (lpszSocketAddress)
  {
    //Convert to an ASCII string
    LPSTR lpszAscii = T2A((LPTSTR) lpszSocketAddress);
    sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);

	  //If the address is not dotted notation, then do a DNS 
	  //lookup of it.
	  if (sockAddr.sin_addr.s_addr == INADDR_NONE)
	  {
		  LPHOSTENT lphost;
		  lphost = gethostbyname(lpszAscii);
		  if (lphost != NULL)
			  sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
		  else
		  {
        AfxThrowWSocketException(WSAEINVAL); 
			  return;
		  }
    }
  }
  else
    sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); //Bind to any IP address;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -