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

📄 socket.cpp.svn-base

📁 絲路server源碼 Silk Road server source
💻 SVN-BASE
📖 第 1 页 / 共 3 页
字号:
/** \file Socket.cpp
 **	\date  2004-02-13
 **	\author grymse@alhem.net
**/
/*
Copyright (C) 2004-2007  Anders Hedstrom

This library is made available under the terms of the GNU GPL.

If you would like to use this library in a closed-source application,
a separate license agreement is available. For information about
the closed-source license agreement for the C++ sockets library,
please visit http://www.alhem.net/Sockets/license.html and/or
email license@alhem.net.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/
#include "Socket.h"
#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning(disable:4786)
#endif
#include <stdlib.h>
#else
#include <errno.h>
#include <netdb.h>
#endif
#include <ctype.h>
#include <fcntl.h>

#include "ISocketHandler.h"
#include "Utility.h"

#include "SocketAddress.h"
#include "SocketHandler.h"
#ifdef ENABLE_EXCEPTIONS
#include "Exception.h"
#endif
#include "Ipv4Address.h"

//#ifdef _DEBUG
//#define DEB(x) x; fflush(stderr);
//#else
#define DEB(x)
//#endif

#ifdef SOCKETS_NAMESPACE
namespace SOCKETS_NAMESPACE {
#endif


// statics
#ifdef _WIN32
WSAInitializer Socket::m_winsock_init;
#endif


Socket::Socket(ISocketHandler& h)
//:m_flags(0)
:m_handler(h)
,m_socket( INVALID_SOCKET )
,m_bDel(false)
,m_bClose(false)
,m_tCreate(time(NULL))
,m_parent(NULL)
,m_b_disable_read(false)
,m_connected(false)
,m_b_erased_by_handler(false)
,m_tClose(0)
,m_client_remote_address(NULL)
,m_remote_address(NULL)
,m_traffic_monitor(NULL)
,m_bLost(false)
#ifdef HAVE_OPENSSL
,m_b_enable_ssl(false)
,m_b_ssl(false)
,m_b_ssl_server(false)
#endif
#ifdef ENABLE_IPV6
,m_ipv6(false)
#endif
#ifdef ENABLE_POOL
,m_socket_type(0)
,m_bClient(false)
,m_bRetain(false)
#endif
#ifdef ENABLE_SOCKS4
,m_bSocks4(false)
,m_socks4_host(h.GetSocks4Host())
,m_socks4_port(h.GetSocks4Port())
,m_socks4_userid(h.GetSocks4Userid())
#endif
#ifdef ENABLE_DETACH
,m_detach(false)
,m_detached(false)
,m_pThread(NULL)
,m_slave_handler(NULL)
#endif
{
}


Socket::~Socket()
{
	Handler().Remove(this);
	if (m_socket != INVALID_SOCKET
#ifdef ENABLE_POOL
		 && !m_bRetain
#endif
		)
	{
		Close();
	}
}


void Socket::Init()
{
}


void Socket::OnRead()
{
}


void Socket::OnWrite()
{
}


void Socket::OnException()
{
	// %! exception doesn't always mean something bad happened, this code should be reworked
	// errno valid here?
	int err = SoError();
	Handler().LogError(this, "exception on select", err, StrError(err), LOG_LEVEL_FATAL);
	SetCloseAndDelete();
}


void Socket::OnDelete()
{
}


void Socket::OnConnect()
{
}


void Socket::OnAccept()
{
}


int Socket::Close()
{
	if (m_socket == INVALID_SOCKET) // this could happen
	{
		Handler().LogError(this, "Socket::Close", 0, "file descriptor invalid", LOG_LEVEL_WARNING);
		return 0;
	}
	int n;
	if ((n = closesocket(m_socket)) == -1)
	{
		// failed...
		Handler().LogError(this, "close", Errno, StrError(Errno), LOG_LEVEL_ERROR);
	}
	Handler().Set(m_socket, false, false, false); // remove from fd_set's
	Handler().AddList(m_socket, LIST_CALLONCONNECT, false);
#ifdef ENABLE_DETACH
	Handler().AddList(m_socket, LIST_DETACH, false);
#endif
	Handler().AddList(m_socket, LIST_TIMEOUT, false);
	Handler().AddList(m_socket, LIST_RETRY, false);
	Handler().AddList(m_socket, LIST_CLOSE, false);
	m_socket = INVALID_SOCKET;
	return n;
}


SOCKET Socket::CreateSocket(int af,int type, const std::string& protocol)
{
	struct protoent *p = NULL;
	SOCKET s;

#ifdef ENABLE_POOL
	m_socket_type = type;
	m_socket_protocol = protocol;
#endif
	if (!protocol.empty())
	{
		p = getprotobyname( protocol.c_str() );
		if (!p)
		{
			Handler().LogError(this, "getprotobyname", Errno, StrError(Errno), LOG_LEVEL_FATAL);
			SetCloseAndDelete();
#ifdef ENABLE_EXCEPTIONS
			throw Exception(std::string("getprotobyname() failed: ") + StrError(Errno));
#endif
			return INVALID_SOCKET;
		}
	}
	int protno = p ? p -> p_proto : 0;

	s = socket(af, type, protno);
	if (s == INVALID_SOCKET)
	{
		Handler().LogError(this, "socket", Errno, StrError(Errno), LOG_LEVEL_FATAL);
		SetCloseAndDelete();
#ifdef ENABLE_EXCEPTIONS
		throw Exception(std::string("socket() failed: ") + StrError(Errno));
#endif
		return INVALID_SOCKET;
	}
	Attach(s);
	OnOptions(af, type, protno, s);
	Attach(INVALID_SOCKET);
	return s;
}


void Socket::Attach(SOCKET s)
{
	m_socket = s;
}


SOCKET Socket::GetSocket()
{
	return m_socket;
}


void Socket::SetDeleteByHandler(bool x)
{
	m_bDel = x;
}


bool Socket::DeleteByHandler()
{
	return m_bDel;
}


void Socket::SetCloseAndDelete(bool x)
{
	if (x != m_bClose)
	{
		Handler().AddList(m_socket, LIST_CLOSE, x);
		m_bClose = x;
		if (x)
		{
			m_tClose = time(NULL);
		}
	}
}


bool Socket::CloseAndDelete()
{
	return m_bClose;
}


void Socket::SetRemoteAddress(SocketAddress& ad) //struct sockaddr* sa, socklen_t l)
{
	m_remote_address = ad.GetCopy();
}


std::auto_ptr<SocketAddress> Socket::GetRemoteSocketAddress()
{
	return m_remote_address -> GetCopy();
}


ISocketHandler& Socket::Handler() const
{
#ifdef ENABLE_DETACH
	if (IsDetached())
		return *m_slave_handler;
#endif
	return m_handler;
}


ISocketHandler& Socket::MasterHandler() const
{
	return m_handler;
}


ipaddr_t Socket::GetRemoteIP4()
{
	ipaddr_t l = 0;
#ifdef ENABLE_IPV6
	if (m_ipv6)
	{
		Handler().LogError(this, "GetRemoteIP4", 0, "get ipv4 address for ipv6 socket", LOG_LEVEL_WARNING);
	}
#endif
	if (m_remote_address.get() != NULL)
	{
		struct sockaddr *p = *m_remote_address;
		struct sockaddr_in *sa = (struct sockaddr_in *)p;
		memcpy(&l, &sa -> sin_addr, sizeof(struct in_addr));
	}
	return l;
}


#ifdef ENABLE_IPV6
#ifdef IPPROTO_IPV6
struct in6_addr Socket::GetRemoteIP6()
{
	if (!m_ipv6)
	{
		Handler().LogError(this, "GetRemoteIP6", 0, "get ipv6 address for ipv4 socket", LOG_LEVEL_WARNING);
	}
	struct sockaddr_in6 fail;
	if (m_remote_address.get() != NULL)
	{
		struct sockaddr *p = *m_remote_address;
		memcpy(&fail, p, sizeof(struct sockaddr_in6));
	}
	else
	{
		memset(&fail, 0, sizeof(struct sockaddr_in6));
	}
	return fail.sin6_addr;
}
#endif
#endif


port_t Socket::GetRemotePort()
{
	if (!m_remote_address.get())
	{
		return 0;
	}
	return m_remote_address -> GetPort();
}


std::string Socket::GetRemoteAddress()
{
	if (!m_remote_address.get())
	{
		return "";
	}
	return m_remote_address -> Convert(false);
}


std::string Socket::GetRemoteHostname()
{
	if (!m_remote_address.get())
	{
		return "";
	}
	return m_remote_address -> Reverse();
}


bool Socket::SetNonblocking(bool bNb)
{
#ifdef _WIN32
	unsigned long l = bNb ? 1 : 0;
	int n = ioctlsocket(m_socket, FIONBIO, &l);
	if (n != 0)
	{
		Handler().LogError(this, "ioctlsocket(FIONBIO)", Errno, "");
		return false;
	}
	return true;
#else
	if (bNb)
	{
		if (fcntl(m_socket, F_SETFL, O_NONBLOCK) == -1)
		{
			Handler().LogError(this, "fcntl(F_SETFL, O_NONBLOCK)", Errno, StrError(Errno), LOG_LEVEL_ERROR);
			return false;
		}
	}
	else
	{
		if (fcntl(m_socket, F_SETFL, 0) == -1)
		{
			Handler().LogError(this, "fcntl(F_SETFL, 0)", Errno, StrError(Errno), LOG_LEVEL_ERROR);
			return false;
		}
	}
	return true;
#endif
}


bool Socket::SetNonblocking(bool bNb, SOCKET s)
{
#ifdef _WIN32
	unsigned long l = bNb ? 1 : 0;
	int n = ioctlsocket(s, FIONBIO, &l);
	if (n != 0)
	{
		Handler().LogError(this, "ioctlsocket(FIONBIO)", Errno, "");
		return false;
	}
	return true;
#else
	if (bNb)
	{
		if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)
		{
			Handler().LogError(this, "fcntl(F_SETFL, O_NONBLOCK)", Errno, StrError(Errno), LOG_LEVEL_ERROR);
			return false;
		}
	}
	else
	{
		if (fcntl(s, F_SETFL, 0) == -1)
		{
			Handler().LogError(this, "fcntl(F_SETFL, 0)", Errno, StrError(Errno), LOG_LEVEL_ERROR);
			return false;
		}
	}
	return true;
#endif
}


void Socket::Set(bool bRead, bool bWrite, bool bException)
{
	Handler().Set(m_socket, bRead, bWrite, bException);
}


bool Socket::Ready()
{
	if (m_socket != INVALID_SOCKET && !CloseAndDelete())
		return true;
	return false;
}


void Socket::OnLine(const std::string& )
{
}


void Socket::OnConnectFailed()
{
}


Socket *Socket::GetParent()
{
	return m_parent;
}


void Socket::SetParent(Socket *x)
{
	m_parent = x;
}


port_t Socket::GetPort()
{
	Handler().LogError(this, "GetPort", 0, "GetPort only implemented for ListenSocket", LOG_LEVEL_WARNING);
	return 0;
}


bool Socket::OnConnectRetry()
{
	return true;
}


#ifdef ENABLE_RECONNECT
void Socket::OnReconnect()
{
}
#endif


time_t Socket::Uptime()
{
	return time(NULL) - m_tCreate;
}


#ifdef ENABLE_IPV6
void Socket::SetIpv6(bool x)
{
	m_ipv6 = x;
}


bool Socket::IsIpv6()
{
	return m_ipv6;
}
#endif


void Socket::DisableRead(bool x)
{
	m_b_disable_read = x;
}


bool Socket::IsDisableRead()
{
	return m_b_disable_read;
}


void Socket::SendBuf(const char *,size_t,int)
{
}


void Socket::Send(const std::string&,int)
{
}


void Socket::SetConnected(bool x)
{
	m_connected = x;
}


bool Socket::IsConnected()
{
	return m_connected;
}


void Socket::OnDisconnect()
{
}


void Socket::SetLost()
{
	m_bLost = true;
}


bool Socket::Lost()
{
	return m_bLost;
}


void Socket::SetErasedByHandler(bool x)
{
	m_b_erased_by_handler = x;
}


bool Socket::ErasedByHandler()
{
	return m_b_erased_by_handler;
}


time_t Socket::TimeSinceClose()
{
	return time(NULL) - m_tClose;
}


void Socket::SetClientRemoteAddress(SocketAddress& ad)
{
	if (!ad.IsValid())
	{
		Handler().LogError(this, "SetClientRemoteAddress", 0, "remote address not valid", LOG_LEVEL_ERROR);
	}
	m_client_remote_address = ad.GetCopy();
}


std::auto_ptr<SocketAddress> Socket::GetClientRemoteAddress()
{
	if (!m_client_remote_address.get())
	{
		Handler().LogError(this, "GetClientRemoteAddress", 0, "remote address not yet set", LOG_LEVEL_ERROR);
	}
	return m_client_remote_address -> GetCopy();
}


uint64_t Socket::GetBytesSent(bool)
{
	return 0;
}


uint64_t Socket::GetBytesReceived(bool)
{
	return 0;
}


#ifdef HAVE_OPENSSL
void Socket::OnSSLConnect()
{
}


void Socket::OnSSLAccept()
{
}

⌨️ 快捷键说明

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