mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-07-07 17:37:12 +02:00
Initial implementation of basic TCP/UDP sockets.
This commit is contained in:
310
module/Vendor/SimpleSocket/ActiveSocket.cpp
vendored
Normal file
310
module/Vendor/SimpleSocket/ActiveSocket.cpp
vendored
Normal file
@ -0,0 +1,310 @@
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* CActiveSocket.cpp - Active Socket Implementation */
|
||||
/* */
|
||||
/* Author : Mark Carrier (mark@carrierlabs.com) */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Copyright (c) 2007-2009 CarrierLabs, LLC. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. The name "CarrierLabs" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* mark@carrierlabs.com.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY MARK CARRIER ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MARK CARRIER OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include "ActiveSocket.h"
|
||||
|
||||
CActiveSocket::CActiveSocket(CSocketType nType) : CSimpleSocket(nType)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// ConnectTCP() -
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CActiveSocket::ConnectTCP(const char *pAddr, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
struct in_addr stIpAddress;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Preconnection setup that must be preformed
|
||||
//------------------------------------------------------------------
|
||||
memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
|
||||
m_stServerSockaddr.sin_family = AF_INET;
|
||||
|
||||
if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
|
||||
{
|
||||
#ifdef WIN32
|
||||
TranslateSocketError();
|
||||
#else
|
||||
if (h_errno == HOST_NOT_FOUND)
|
||||
{
|
||||
SetSocketError(SocketInvalidAddress);
|
||||
}
|
||||
#endif
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
|
||||
m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
|
||||
|
||||
if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
|
||||
{
|
||||
TranslateSocketError();
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
m_stServerSockaddr.sin_port = htons(nPort);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) ==
|
||||
CSimpleSocket::SocketError)
|
||||
{
|
||||
//--------------------------------------------------------------
|
||||
// Get error value this might be a non-blocking socket so we
|
||||
// must first check.
|
||||
//--------------------------------------------------------------
|
||||
TranslateSocketError();
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// If the socket is non-blocking and the current socket error
|
||||
// is SocketEinprogress or SocketEwouldblock then poll connection
|
||||
// with select for designated timeout period.
|
||||
// Linux returns EINPROGRESS and Windows returns WSAEWOULDBLOCK.
|
||||
//--------------------------------------------------------------
|
||||
if ((IsNonblocking()) &&
|
||||
((GetSocketError() == CSimpleSocket::SocketEwouldblock) ||
|
||||
(GetSocketError() == CSimpleSocket::SocketEinprogress)))
|
||||
{
|
||||
bRetVal = Select(GetConnectTimeoutSec(), GetConnectTimeoutUSec());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslateSocketError();
|
||||
bRetVal = true;
|
||||
}
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// ConnectUDP() -
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CActiveSocket::ConnectUDP(const char *pAddr, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
struct in_addr stIpAddress;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Pre-connection setup that must be preformed
|
||||
//------------------------------------------------------------------
|
||||
memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
|
||||
m_stServerSockaddr.sin_family = AF_INET;
|
||||
|
||||
if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
|
||||
{
|
||||
#ifdef WIN32
|
||||
TranslateSocketError();
|
||||
#else
|
||||
if (h_errno == HOST_NOT_FOUND)
|
||||
{
|
||||
SetSocketError(SocketInvalidAddress);
|
||||
}
|
||||
#endif
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
|
||||
m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
|
||||
|
||||
if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
|
||||
{
|
||||
TranslateSocketError();
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
m_stServerSockaddr.sin_port = htons(nPort);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
|
||||
{
|
||||
bRetVal = true;
|
||||
}
|
||||
|
||||
TranslateSocketError();
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// ConnectRAW() -
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CActiveSocket::ConnectRAW(const char *pAddr, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
struct in_addr stIpAddress;
|
||||
//------------------------------------------------------------------
|
||||
// Pre-connection setup that must be preformed
|
||||
//------------------------------------------------------------------
|
||||
memset(&m_stServerSockaddr, 0, sizeof(m_stServerSockaddr));
|
||||
m_stServerSockaddr.sin_family = AF_INET;
|
||||
|
||||
if ((m_pHE = GETHOSTBYNAME(pAddr)) == NULL)
|
||||
{
|
||||
#ifdef WIN32
|
||||
TranslateSocketError();
|
||||
#else
|
||||
if (h_errno == HOST_NOT_FOUND)
|
||||
{
|
||||
SetSocketError(SocketInvalidAddress);
|
||||
}
|
||||
#endif
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
memcpy(&stIpAddress, m_pHE->h_addr_list[0], m_pHE->h_length);
|
||||
m_stServerSockaddr.sin_addr.s_addr = stIpAddress.s_addr;
|
||||
|
||||
if ((int32)m_stServerSockaddr.sin_addr.s_addr == CSimpleSocket::SocketError)
|
||||
{
|
||||
TranslateSocketError();
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
m_stServerSockaddr.sin_port = htons(nPort);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Connect to address "xxx.xxx.xxx.xxx" (IPv4) address only.
|
||||
//
|
||||
//------------------------------------------------------------------
|
||||
m_timer.Initialize();
|
||||
m_timer.SetStartTime();
|
||||
|
||||
if (connect(m_socket, (struct sockaddr*)&m_stServerSockaddr, sizeof(m_stServerSockaddr)) != CSimpleSocket::SocketError)
|
||||
{
|
||||
bRetVal = true;
|
||||
}
|
||||
|
||||
TranslateSocketError();
|
||||
|
||||
m_timer.SetEndTime();
|
||||
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Open() - Create a connection to a specified address on a specified port
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
bool CActiveSocket::Open(const char *pAddr, uint16 nPort)
|
||||
{
|
||||
bool bRetVal = false;
|
||||
|
||||
if (IsSocketValid() == false)
|
||||
{
|
||||
SetSocketError(CSimpleSocket::SocketInvalidSocket);
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
if (pAddr == NULL)
|
||||
{
|
||||
SetSocketError(CSimpleSocket::SocketInvalidAddress);
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
if (nPort == 0)
|
||||
{
|
||||
SetSocketError(CSimpleSocket::SocketInvalidPort);
|
||||
return bRetVal;
|
||||
}
|
||||
|
||||
switch (m_nSocketType)
|
||||
{
|
||||
case CSimpleSocket::SocketTypeTcp :
|
||||
{
|
||||
bRetVal = ConnectTCP(pAddr, nPort);
|
||||
break;
|
||||
}
|
||||
case CSimpleSocket::SocketTypeUdp :
|
||||
{
|
||||
bRetVal = ConnectUDP(pAddr, nPort);
|
||||
break;
|
||||
}
|
||||
case CSimpleSocket::SocketTypeRaw :
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// If successful then create a local copy of the address and port
|
||||
//--------------------------------------------------------------------------
|
||||
if (bRetVal)
|
||||
{
|
||||
socklen_t nSockLen = sizeof(struct sockaddr);
|
||||
|
||||
memset(&m_stServerSockaddr, 0, nSockLen);
|
||||
getpeername(m_socket, (struct sockaddr *)&m_stServerSockaddr, &nSockLen);
|
||||
|
||||
nSockLen = sizeof(struct sockaddr);
|
||||
memset(&m_stClientSockaddr, 0, nSockLen);
|
||||
getsockname(m_socket, (struct sockaddr *)&m_stClientSockaddr, &nSockLen);
|
||||
|
||||
SetSocketError(SocketSuccess);
|
||||
}
|
||||
|
||||
return bRetVal;
|
||||
}
|
Reference in New Issue
Block a user