Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Tagged as

Implementation of the Licensing System for a Software Product

, , 5 Aug 2010 CPOL
This article is devoted to the development of the key licensing system for the applications.
bin.zip
bin
ClientTest.exe
DigitalSignature.exe
src.zip
src
src
ClientTest
keys
public.bin
cryptopp560
adhoc.cpp.copied
adhoc.cpp.proto
cryptdll.dsp
cryptest.dsp
cryptest.dsw
cryptest_bds.bdsgroup
cryptest_bds.bdsproj
cryptest_bds.bpf
cryptlib.dsp
cryptlib_bds.bdsproj
dlltest.dsp
Doxyfile
GNUmakefile
DigitalSignature
keys
private.bin
public.bin
Utils
// socketft.cpp - written and placed in the public domain by Wei Dai

#include "pch.h"
#include "socketft.h"

#ifdef SOCKETS_AVAILABLE

#include "wait.h"

#ifdef USE_BERKELEY_STYLE_SOCKETS
#include <errno.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#endif

NAMESPACE_BEGIN(CryptoPP)

#ifdef USE_WINDOWS_STYLE_SOCKETS
const int SOCKET_EINVAL = WSAEINVAL;
const int SOCKET_EWOULDBLOCK = WSAEWOULDBLOCK;
typedef int socklen_t;
#else
const int SOCKET_EINVAL = EINVAL;
const int SOCKET_EWOULDBLOCK = EWOULDBLOCK;
#endif

Socket::Err::Err(socket_t s, const std::string& operation, int error)
	: OS_Error(IO_ERROR, "Socket: " + operation + " operation failed with error " + IntToString(error), operation, error)
	, m_s(s)
{
}

Socket::~Socket()
{
	if (m_own)
	{
		try
		{
			CloseSocket();
		}
		catch (...)
		{
		}
	}
}

void Socket::AttachSocket(socket_t s, bool own)
{
	if (m_own)
		CloseSocket();

	m_s = s;
	m_own = own;
	SocketChanged();
}

socket_t Socket::DetachSocket()
{
	socket_t s = m_s;
	m_s = INVALID_SOCKET;
	SocketChanged();
	return s;
}

void Socket::Create(int nType)
{
	assert(m_s == INVALID_SOCKET);
	m_s = socket(AF_INET, nType, 0);
	CheckAndHandleError("socket", m_s);
	m_own = true;
	SocketChanged();
}

void Socket::CloseSocket()
{
	if (m_s != INVALID_SOCKET)
	{
#ifdef USE_WINDOWS_STYLE_SOCKETS
		CancelIo((HANDLE) m_s);
		CheckAndHandleError_int("closesocket", closesocket(m_s));
#else
		CheckAndHandleError_int("close", close(m_s));
#endif
		m_s = INVALID_SOCKET;
		SocketChanged();
	}
}

void Socket::Bind(unsigned int port, const char *addr)
{
	sockaddr_in sa;
	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;

	if (addr == NULL)
		sa.sin_addr.s_addr = htonl(INADDR_ANY);
	else
	{
		unsigned long result = inet_addr(addr);
		if (result == -1)	// Solaris doesn't have INADDR_NONE
		{
			SetLastError(SOCKET_EINVAL);
			CheckAndHandleError_int("inet_addr", SOCKET_ERROR);
		}
		sa.sin_addr.s_addr = result;
	}

	sa.sin_port = htons((u_short)port);

	Bind((sockaddr *)&sa, sizeof(sa));
}

void Socket::Bind(const sockaddr *psa, socklen_t saLen)
{
	assert(m_s != INVALID_SOCKET);
	// cygwin workaround: needs const_cast
	CheckAndHandleError_int("bind", bind(m_s, const_cast<sockaddr *>(psa), saLen));
}

void Socket::Listen(int backlog)
{
	assert(m_s != INVALID_SOCKET);
	CheckAndHandleError_int("listen", listen(m_s, backlog));
}

bool Socket::Connect(const char *addr, unsigned int port)
{
	assert(addr != NULL);

	sockaddr_in sa;
	memset(&sa, 0, sizeof(sa));
	sa.sin_family = AF_INET;
	sa.sin_addr.s_addr = inet_addr(addr);

	if (sa.sin_addr.s_addr == -1)	// Solaris doesn't have INADDR_NONE
	{
		hostent *lphost = gethostbyname(addr);
		if (lphost == NULL)
		{
			SetLastError(SOCKET_EINVAL);
			CheckAndHandleError_int("gethostbyname", SOCKET_ERROR);
		}

		sa.sin_addr.s_addr = ((in_addr *)lphost->h_addr)->s_addr;
	}

	sa.sin_port = htons((u_short)port);

	return Connect((const sockaddr *)&sa, sizeof(sa));
}

bool Socket::Connect(const sockaddr* psa, socklen_t saLen)
{
	assert(m_s != INVALID_SOCKET);
	int result = connect(m_s, const_cast<sockaddr*>(psa), saLen);
	if (result == SOCKET_ERROR && GetLastError() == SOCKET_EWOULDBLOCK)
		return false;
	CheckAndHandleError_int("connect", result);
	return true;
}

bool Socket::Accept(Socket& target, sockaddr *psa, socklen_t *psaLen)
{
	assert(m_s != INVALID_SOCKET);
	socket_t s = accept(m_s, psa, psaLen);
	if (s == INVALID_SOCKET && GetLastError() == SOCKET_EWOULDBLOCK)
		return false;
	CheckAndHandleError("accept", s);
	target.AttachSocket(s, true);
	return true;
}

void Socket::GetSockName(sockaddr *psa, socklen_t *psaLen)
{
	assert(m_s != INVALID_SOCKET);
	CheckAndHandleError_int("getsockname", getsockname(m_s, psa, psaLen));
}

void Socket::GetPeerName(sockaddr *psa, socklen_t *psaLen)
{
	assert(m_s != INVALID_SOCKET);
	CheckAndHandleError_int("getpeername", getpeername(m_s, psa, psaLen));
}

unsigned int Socket::Send(const byte* buf, size_t bufLen, int flags)
{
	assert(m_s != INVALID_SOCKET);
	int result = send(m_s, (const char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
	CheckAndHandleError_int("send", result);
	return result;
}

unsigned int Socket::Receive(byte* buf, size_t bufLen, int flags)
{
	assert(m_s != INVALID_SOCKET);
	int result = recv(m_s, (char *)buf, UnsignedMin(INT_MAX, bufLen), flags);
	CheckAndHandleError_int("recv", result);
	return result;
}

void Socket::ShutDown(int how)
{
	assert(m_s != INVALID_SOCKET);
	int result = shutdown(m_s, how);
	CheckAndHandleError_int("shutdown", result);
}

void Socket::IOCtl(long cmd, unsigned long *argp)
{
	assert(m_s != INVALID_SOCKET);
#ifdef USE_WINDOWS_STYLE_SOCKETS
	CheckAndHandleError_int("ioctlsocket", ioctlsocket(m_s, cmd, argp));
#else
	CheckAndHandleError_int("ioctl", ioctl(m_s, cmd, argp));
#endif
}

bool Socket::SendReady(const timeval *timeout)
{
	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(m_s, &fds);
	int ready;
	if (timeout == NULL)
		ready = select((int)m_s+1, NULL, &fds, NULL, NULL);
	else
	{
		timeval timeoutCopy = *timeout;	// select() modified timeout on Linux
		ready = select((int)m_s+1, NULL, &fds, NULL, &timeoutCopy);
	}
	CheckAndHandleError_int("select", ready);
	return ready > 0;
}

bool Socket::ReceiveReady(const timeval *timeout)
{
	fd_set fds;
	FD_ZERO(&fds);
	FD_SET(m_s, &fds);
	int ready;
	if (timeout == NULL)
		ready = select((int)m_s+1, &fds, NULL, NULL, NULL);
	else
	{
		timeval timeoutCopy = *timeout;	// select() modified timeout on Linux
		ready = select((int)m_s+1, &fds, NULL, NULL, &timeoutCopy);
	}
	CheckAndHandleError_int("select", ready);
	return ready > 0;
}

unsigned int Socket::PortNameToNumber(const char *name, const char *protocol)
{
	int port = atoi(name);
	if (IntToString(port) == name)
		return port;

	servent *se = getservbyname(name, protocol);
	if (!se)
		throw Err(INVALID_SOCKET, "getservbyname", SOCKET_EINVAL);
	return ntohs(se->s_port);
}

void Socket::StartSockets()
{
#ifdef USE_WINDOWS_STYLE_SOCKETS
	WSADATA wsd;
	int result = WSAStartup(0x0202, &wsd);
	if (result != 0)
		throw Err(INVALID_SOCKET, "WSAStartup", result);
#endif
}

void Socket::ShutdownSockets()
{
#ifdef USE_WINDOWS_STYLE_SOCKETS
	int result = WSACleanup();
	if (result != 0)
		throw Err(INVALID_SOCKET, "WSACleanup", result);
#endif
}

int Socket::GetLastError()
{
#ifdef USE_WINDOWS_STYLE_SOCKETS
	return WSAGetLastError();
#else
	return errno;
#endif
}

void Socket::SetLastError(int errorCode)
{
#ifdef USE_WINDOWS_STYLE_SOCKETS
	WSASetLastError(errorCode);
#else
	errno = errorCode;
#endif
}

void Socket::HandleError(const char *operation) const
{
	int err = GetLastError();
	throw Err(m_s, operation, err);
}

#ifdef USE_WINDOWS_STYLE_SOCKETS

SocketReceiver::SocketReceiver(Socket &s)
	: m_s(s), m_resultPending(false), m_eofReceived(false)
{
	m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
	m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
	memset(&m_overlapped, 0, sizeof(m_overlapped));
	m_overlapped.hEvent = m_event;
}

SocketReceiver::~SocketReceiver()
{
#ifdef USE_WINDOWS_STYLE_SOCKETS
	CancelIo((HANDLE) m_s.GetSocket());
#endif
}

bool SocketReceiver::Receive(byte* buf, size_t bufLen)
{
	assert(!m_resultPending && !m_eofReceived);

	DWORD flags = 0;
	// don't queue too much at once, or we might use up non-paged memory
	WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
	if (WSARecv(m_s, &wsabuf, 1, &m_lastResult, &flags, &m_overlapped, NULL) == 0)
	{
		if (m_lastResult == 0)
			m_eofReceived = true;
	}
	else
	{
		switch (WSAGetLastError())
		{
		default:
			m_s.CheckAndHandleError_int("WSARecv", SOCKET_ERROR);
		case WSAEDISCON:
			m_lastResult = 0;
			m_eofReceived = true;
			break;
		case WSA_IO_PENDING:
			m_resultPending = true;
		}
	}
	return !m_resultPending;
}

void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
{
	if (m_resultPending)
		container.AddHandle(m_event, CallStack("SocketReceiver::GetWaitObjects() - result pending", &callStack));
	else if (!m_eofReceived)
		container.SetNoWait(CallStack("SocketReceiver::GetWaitObjects() - result ready", &callStack));
}

unsigned int SocketReceiver::GetReceiveResult()
{
	if (m_resultPending)
	{
		DWORD flags = 0;
		if (WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags))
		{
			if (m_lastResult == 0)
				m_eofReceived = true;
		}
		else
		{
			switch (WSAGetLastError())
			{
			default:
				m_s.CheckAndHandleError("WSAGetOverlappedResult", FALSE);
			case WSAEDISCON:
				m_lastResult = 0;
				m_eofReceived = true;
			}
		}
		m_resultPending = false;
	}
	return m_lastResult;
}

// *************************************************************

SocketSender::SocketSender(Socket &s)
	: m_s(s), m_resultPending(false), m_lastResult(0)
{
	m_event.AttachHandle(CreateEvent(NULL, true, false, NULL), true);
	m_s.CheckAndHandleError("CreateEvent", m_event.HandleValid());
	memset(&m_overlapped, 0, sizeof(m_overlapped));
	m_overlapped.hEvent = m_event;
}


SocketSender::~SocketSender()
{
#ifdef USE_WINDOWS_STYLE_SOCKETS
	CancelIo((HANDLE) m_s.GetSocket());
#endif
}

void SocketSender::Send(const byte* buf, size_t bufLen)
{
	assert(!m_resultPending);
	DWORD written = 0;
	// don't queue too much at once, or we might use up non-paged memory
	WSABUF wsabuf = {UnsignedMin((u_long)128*1024, bufLen), (char *)buf};
	if (WSASend(m_s, &wsabuf, 1, &written, 0, &m_overlapped, NULL) == 0)
	{
		m_resultPending = false;
		m_lastResult = written;
	}
	else
	{
		if (WSAGetLastError() != WSA_IO_PENDING)
			m_s.CheckAndHandleError_int("WSASend", SOCKET_ERROR);

		m_resultPending = true;
	}
}

void SocketSender::SendEof()
{
	assert(!m_resultPending);
	m_s.ShutDown(SD_SEND);
	m_s.CheckAndHandleError("ResetEvent", ResetEvent(m_event));
	m_s.CheckAndHandleError_int("WSAEventSelect", WSAEventSelect(m_s, m_event, FD_CLOSE));
	m_resultPending = true;
}

bool SocketSender::EofSent()
{
	if (m_resultPending)
	{
		WSANETWORKEVENTS events;
		m_s.CheckAndHandleError_int("WSAEnumNetworkEvents", WSAEnumNetworkEvents(m_s, m_event, &events));
		if ((events.lNetworkEvents & FD_CLOSE) != FD_CLOSE)
			throw Socket::Err(m_s, "WSAEnumNetworkEvents (FD_CLOSE not present)", E_FAIL);
		if (events.iErrorCode[FD_CLOSE_BIT] != 0)
			throw Socket::Err(m_s, "FD_CLOSE (via WSAEnumNetworkEvents)", events.iErrorCode[FD_CLOSE_BIT]);
		m_resultPending = false;
	}
	return m_lastResult != 0;
}

void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
{
	if (m_resultPending)
		container.AddHandle(m_event, CallStack("SocketSender::GetWaitObjects() - result pending", &callStack));
	else
		container.SetNoWait(CallStack("SocketSender::GetWaitObjects() - result ready", &callStack));
}

unsigned int SocketSender::GetSendResult()
{
	if (m_resultPending)
	{
		DWORD flags = 0;
		BOOL result = WSAGetOverlappedResult(m_s, &m_overlapped, &m_lastResult, false, &flags);
		m_s.CheckAndHandleError("WSAGetOverlappedResult", result);
		m_resultPending = false;
	}
	return m_lastResult;
}

#endif

#ifdef USE_BERKELEY_STYLE_SOCKETS

SocketReceiver::SocketReceiver(Socket &s)
	: m_s(s), m_lastResult(0), m_eofReceived(false)
{
}

void SocketReceiver::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
{
	if (!m_eofReceived)
		container.AddReadFd(m_s, CallStack("SocketReceiver::GetWaitObjects()", &callStack));
}

bool SocketReceiver::Receive(byte* buf, size_t bufLen)
{
	m_lastResult = m_s.Receive(buf, bufLen);
	if (bufLen > 0 && m_lastResult == 0)
		m_eofReceived = true;
	return true;
}

unsigned int SocketReceiver::GetReceiveResult()
{
	return m_lastResult;
}

SocketSender::SocketSender(Socket &s)
	: m_s(s), m_lastResult(0)
{
}

void SocketSender::Send(const byte* buf, size_t bufLen)
{
	m_lastResult = m_s.Send(buf, bufLen);
}

void SocketSender::SendEof()
{
	m_s.ShutDown(SD_SEND);
}

unsigned int SocketSender::GetSendResult()
{
	return m_lastResult;
}

void SocketSender::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
{
	container.AddWriteFd(m_s, CallStack("SocketSender::GetWaitObjects()", &callStack));
}

#endif

NAMESPACE_END

#endif	// #ifdef SOCKETS_AVAILABLE

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Authors

Apriorit Inc
Apriorit Inc.
Ukraine Ukraine
ApriorIT is a Software Research and Development company that works in advanced knowledge-intensive scopes.
 
Company offers integrated research&development services for the software projects in such directions as Corporate Security, Remote Control, Mobile Development, Embedded Systems, Virtualization, Drivers and others.
 
Official site http://www.apriorit.com
Group type: Organisation

31 members

Follow on   LinkedIn

Sergii Bratus
Software Developer Apriorit Inc.
Ukraine Ukraine
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411022.1 | Last Updated 5 Aug 2010
Article Copyright 2010 by Apriorit Inc, Sergii Bratus
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid