18 changed files with 1716 additions and 2 deletions
@ -0,0 +1,770 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// BaseCrossSocket.cpp
|
|||
|
|||
#include "BaseCrossSocket.h" |
|||
#include "CrossSocketPlatform.h" |
|||
#include "CrossSocket.h" |
|||
#include "CrossThreads.h" |
|||
#include "CrossThreadsHandler.h" |
|||
|
|||
#include <errno.h> |
|||
#include <new> |
|||
#include <time.h> |
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
#include <iostream> |
|||
|
|||
// Create the constructor
|
|||
BaseCrossSocket::BaseCrossSocket() |
|||
{ |
|||
_socketHandle = -1; |
|||
_closeSignal = false; |
|||
|
|||
// Initialize default values
|
|||
_error = ""; |
|||
_blockingMode = nonblocking; |
|||
_timeoutSeconds = 0; |
|||
_timeoutMicroSeconds = 0; |
|||
_password = ""; |
|||
_threadHandler = new CrossThreadsHandler(); |
|||
|
|||
#ifdef __WIN32__ |
|||
static bool firstTime = true; |
|||
if (firstTime) |
|||
{ |
|||
WSAData wsaData; |
|||
|
|||
if ((int i = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) |
|||
{ |
|||
handleError(NULL, "BaseCrossSocket - WSAStartup() failed: "); |
|||
exit(-1); |
|||
} |
|||
|
|||
// cleanup
|
|||
atexit(WSA_exit); |
|||
firstTime = false; |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
BaseCrossSocket::~BaseCrossSocket() |
|||
{ |
|||
if (_socketHandle > 0) |
|||
{ |
|||
close(_socketHandle); |
|||
} |
|||
} |
|||
|
|||
bool BaseCrossSocket::listen(int connectionLimit, CrossSocketErrors *error) |
|||
{ |
|||
fprintf(stderr,"This application is using: CrossSockets\n" |
|||
" Created by Jeroen Saey\n" |
|||
"========================================\n"); |
|||
|
|||
getSocket(); |
|||
|
|||
char alreadyInUse = 1; |
|||
setsockopt(_socketHandle, SOL_SOCKET, SO_REUSEADDR, &alreadyInUse, sizeof(int)); |
|||
|
|||
if(::listen(_socketHandle, connectionLimit) == -1) |
|||
{ |
|||
handleError(error, "BaseCrossSocket::listen() error: "); |
|||
return false; |
|||
} |
|||
|
|||
noError(error); |
|||
return true; |
|||
} |
|||
|
|||
BaseCrossSocket* BaseCrossSocket::accept(CrossSocketErrors *error) |
|||
{ |
|||
int remoteSocketHandle = -1; |
|||
sockaddr remoteAddress; |
|||
|
|||
if (!waitRead(error)) |
|||
{ |
|||
return NULL; |
|||
} |
|||
|
|||
sw_socklen_t socketSize = sizeof(sockaddr); |
|||
|
|||
if ((remoteSocketHandle = ::accept(_socketHandle, &remoteAddress, &socketSize)) == int(SOCKETFAIL)) |
|||
{ |
|||
handleError(error, "BaseCrossSocket::accept() error: "); |
|||
return NULL; |
|||
} |
|||
|
|||
// Check if we are in non blocking mode
|
|||
if (_blockingMode == nonblocking) |
|||
{ |
|||
fcntl(remoteSocketHandle, F_SETFL, O_NONBLOCK); |
|||
} |
|||
|
|||
// Create a new class of the BaseCrossSocket
|
|||
BaseCrossSocket* clientSocket = create(remoteSocketHandle, error); |
|||
|
|||
noError(error); |
|||
|
|||
stringstream clientInformation; |
|||
clientInformation << ((CrossSocket*)clientSocket)->getClientAddress() << " is connected!\n" |
|||
<< ((CrossSocket*)clientSocket)->getClientAddress() << " : " << ((CrossSocket*)clientSocket)->getClientPort() << "\n"; |
|||
|
|||
cout << clientInformation.str(); |
|||
|
|||
return clientSocket; |
|||
} |
|||
|
|||
bool BaseCrossSocket::checkPassword(BaseCrossSocket *socket) |
|||
{ |
|||
if (_password.length() > 0) |
|||
{ |
|||
socket->writeLine("This server is protected with a password, please insert the password now."); |
|||
|
|||
int passwordCounter = 0; |
|||
string givenPassword; |
|||
while (givenPassword != _password) |
|||
{ |
|||
// Just read 50 bytes for the password
|
|||
givenPassword = socket->readLine(50); |
|||
if (givenPassword != _password) |
|||
{ |
|||
socket->writeLine("Incorrect password given."); |
|||
passwordCounter++; |
|||
if (passwordCounter >= 5) |
|||
{ |
|||
socket->writeLine("Too many attempts where made to enter the correct password."); |
|||
socket->writeLine("Have a nice day!"); |
|||
socket->writeLine("Disconnecting..."); |
|||
socket->writeLine("403"); |
|||
disconnect(); |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
socket->writeLine("The password is correct. Access granted"); |
|||
return true; |
|||
} |
|||
|
|||
bool BaseCrossSocket::isConnected() |
|||
{ |
|||
return _socketHandle > 0; |
|||
} |
|||
|
|||
bool BaseCrossSocket::disconnect(CrossSocketErrors *error) |
|||
{ |
|||
int i = 0; |
|||
char buffer[256]; |
|||
|
|||
if (_socketHandle < 0) |
|||
{ |
|||
setError(error, notConnected, "BaseCrossSocket::disconnect() - No connection"); |
|||
return false; |
|||
} |
|||
|
|||
// check if the client closed the connection
|
|||
if (shutdown(_socketHandle, 1) != 0) |
|||
{ |
|||
handleError(error, "BaseCrossSocket::disconnect() error: "); |
|||
return false; |
|||
} |
|||
|
|||
CrossSocketErrors crossSocketError; |
|||
|
|||
// Check if we got a signal from the client that he closed the connection
|
|||
if (!_closeSignal) |
|||
{ |
|||
while (true) |
|||
{ |
|||
if (!waitRead(error)) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
i = readLine(buffer, 256, &crossSocketError); |
|||
|
|||
if (i <= 0) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
// If we do not want to wait we need to throw an error
|
|||
if (_blockingMode == noWait) |
|||
{ |
|||
setError(error, notReady, "BaseCrossSocket::disconnect() - We need more time, please call again"); |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (i != 0) |
|||
{ |
|||
setError(error, crossSocketError, _error); |
|||
return false; |
|||
} |
|||
|
|||
// Reset the state
|
|||
reset(); |
|||
|
|||
close(_socketHandle); |
|||
_socketHandle = -1; |
|||
|
|||
noError(error); |
|||
cout << "CrossSockets: Client has been disconnected!\n"; |
|||
return true; |
|||
} |
|||
|
|||
bool BaseCrossSocket::closeSocketHandle() |
|||
{ |
|||
if (_socketHandle > 0) |
|||
{ |
|||
close(_socketHandle); |
|||
_socketHandle = -1; |
|||
|
|||
//reset state
|
|||
reset(); |
|||
|
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
int BaseCrossSocket::writeLine(string message, CrossSocketErrors *error) |
|||
{ |
|||
//TODO: Why cant we append the data?
|
|||
//int returnValue = send(_socketHandle, message.append("\r\n").data(), strlen(message.data()), 0);
|
|||
int returnValue = send(_socketHandle, message.data(), message.size(), 0); |
|||
send(_socketHandle, "\r\n", 2, 0); |
|||
return returnValue; |
|||
} |
|||
|
|||
int BaseCrossSocket::writeLine(string message, size_t length, CrossSocketErrors *error) |
|||
{ |
|||
int returnValue = send(_socketHandle, message.data(), length, 0); |
|||
send(_socketHandle, "\r\n", 2, 0); |
|||
return returnValue; |
|||
} |
|||
|
|||
int BaseCrossSocket::write(const string message, size_t length, CrossSocketErrors *error) |
|||
{ |
|||
return send(_socketHandle, message.data(), length, 0); |
|||
} |
|||
|
|||
int BaseCrossSocket::write(const string message, CrossSocketErrors *error) |
|||
{ |
|||
return send(_socketHandle, message.data(), message.size(), 0); |
|||
} |
|||
|
|||
void BaseCrossSocket::setPassword(const string password) |
|||
{ |
|||
_password = password; |
|||
} |
|||
|
|||
ssize_t BaseCrossSocket::read(char *buffer, CrossSocketErrors *error) |
|||
{ |
|||
ssize_t returnValue = 0; |
|||
char singleCharacter; |
|||
|
|||
if (_socketHandle < 0) |
|||
{ |
|||
setError(error, notConnected, "BaseCrossSocket::read() - No connection"); |
|||
return -1; |
|||
} |
|||
|
|||
if (!waitRead(error)) |
|||
{ |
|||
return -1; |
|||
} |
|||
|
|||
while (size_t i = recv(_socketHandle, buffer + returnValue, int(sizeof(buffer) - returnValue), 0)) |
|||
{ |
|||
if (i == 0) |
|||
{ |
|||
break; |
|||
} |
|||
returnValue += i; |
|||
if (returnValue > sizeof(buffer) -1) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
return returnValue; |
|||
} |
|||
|
|||
ssize_t BaseCrossSocket::read(char *buffer, int bytes, CrossSocketErrors *error) |
|||
{ |
|||
ssize_t returnValue = 0; |
|||
char singleCharacter; |
|||
|
|||
if (_socketHandle < 0) |
|||
{ |
|||
setError(error, notConnected, "BaseCrossSocket::read() - No connection"); |
|||
return -1; |
|||
} |
|||
|
|||
if (!waitRead(error)) |
|||
{ |
|||
return -1; |
|||
} |
|||
|
|||
while (size_t i = recv(_socketHandle, buffer + returnValue, int(bytes - returnValue), 0)) |
|||
{ |
|||
if (i == 0) |
|||
{ |
|||
break; |
|||
} |
|||
returnValue += i; |
|||
if (returnValue > bytes -1) |
|||
{ |
|||
break; |
|||
} |
|||
} |
|||
return returnValue; |
|||
} |
|||
|
|||
string BaseCrossSocket::readLine(int size, CrossSocketErrors *error) |
|||
{ |
|||
char *buffer = new char[size]; |
|||
ssize_t returnValue = 0; |
|||
char singleCharacter; |
|||
|
|||
if (_socketHandle < 0) |
|||
{ |
|||
setError(error, notConnected, "BaseCrossSocket::readLine() - No connection"); |
|||
} |
|||
|
|||
if (!waitRead(error)) |
|||
{ |
|||
return string(); |
|||
} |
|||
|
|||
while (size_t i = recv(_socketHandle, &singleCharacter, 1, 0)) |
|||
{ |
|||
if (returnValue >= size || singleCharacter == '\n') |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
if (singleCharacter != '\r') |
|||
{ |
|||
buffer[returnValue++] = singleCharacter; |
|||
} |
|||
} |
|||
buffer[returnValue] = '\0'; |
|||
|
|||
if (returnValue < 0) |
|||
{ |
|||
handleError(error, "BaseCrossSocket::readLine() error: "); |
|||
} |
|||
else if (returnValue == 0) |
|||
{ |
|||
_closeSignal = true; //we received a close signal from client
|
|||
setError(error, terminated, "BaseCrossSocket::readLine() - Connection terminated by client"); |
|||
} |
|||
else |
|||
{ |
|||
noError(error); |
|||
} |
|||
return string(buffer); |
|||
} |
|||
|
|||
ssize_t BaseCrossSocket::readLine(char *buffer, int bytes, CrossSocketErrors *error) |
|||
{ |
|||
ssize_t returnValue = 0; |
|||
char singleCharacter; |
|||
|
|||
if (_socketHandle < 0) |
|||
{ |
|||
setError(error, notConnected, "BaseCrossSocket::readLine() - No connection"); |
|||
return -1; |
|||
} |
|||
|
|||
if (!waitRead(error)) |
|||
{ |
|||
return -1; |
|||
} |
|||
|
|||
while (size_t i = recv(_socketHandle, &singleCharacter, 1, 0)) |
|||
{ |
|||
if (returnValue >= sizeof(buffer) || singleCharacter == '\n') |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
if (singleCharacter != '\r') |
|||
{ |
|||
buffer[returnValue++] = singleCharacter; |
|||
} |
|||
} |
|||
buffer[returnValue] = '\0'; |
|||
|
|||
if (returnValue < 0) |
|||
{ |
|||
handleError(error, "BaseCrossSocket::readLine() error: "); |
|||
} |
|||
else if (returnValue == 0) |
|||
{ |
|||
_closeSignal = true; //we received a close signal from client
|
|||
setError(error, terminated, "BaseCrossSocket::readLine() - Connection terminated by client"); |
|||
} |
|||
else |
|||
{ |
|||
noError(error); |
|||
} |
|||
return returnValue; |
|||
} |
|||
|
|||
int BaseCrossSocket::getClientSocket(CrossSocketErrors *error) |
|||
{ |
|||
if (_socketHandle > 0) |
|||
{ |
|||
noError(error); |
|||
return _socketHandle; |
|||
} |
|||
|
|||
setError(error, notConnected, "BaseCrossSocket::getClientSocket() - No descriptor"); |
|||
return -1; |
|||
} |
|||
|
|||
bool BaseCrossSocket::getServerHost(sockaddr *host, CrossSocketErrors *error) |
|||
{ |
|||
if (host == NULL) |
|||
{ |
|||
setError(error, fatal, "BaseCrossSocket::getServerHost() - Got NULL pointer"); |
|||
return false; |
|||
} |
|||
|
|||
if (_socketHandle < 0) |
|||
{ |
|||
setError(error, notConnected, "BaseCrossSocket::getServerHost() - No socket"); |
|||
return false; |
|||
} |
|||
|
|||
sw_socklen_t temp = sizeof(sockaddr); |
|||
if (getsockname(_socketHandle, host, &temp) != 0) |
|||
{ |
|||
handleError(error, "BaseCrossSocket::getServerHost() error: "); |
|||
return false; |
|||
} |
|||
|
|||
noError(error); |
|||
return true; |
|||
} |
|||
|
|||
void BaseCrossSocket::setTimeout(unsigned int seconds, unsigned int miliSeconds) |
|||
{ |
|||
_timeoutSeconds = seconds; |
|||
_timeoutMicroSeconds = miliSeconds; |
|||
} |
|||
|
|||
bool BaseCrossSocket::getClientHost(sockaddr *client, CrossSocketErrors *error) |
|||
{ |
|||
if (client == NULL) |
|||
{ |
|||
setError(error, fatal, "BaseCrossSocket::getClientHost() - Got NULL pointer"); |
|||
return false; |
|||
} |
|||
|
|||
if (_socketHandle > 0) |
|||
{ |
|||
sw_socklen_t temp = sizeof(sockaddr); |
|||
|
|||
if (getpeername(_socketHandle, client, &temp) != 0) |
|||
{ |
|||
handleError(error, "BaseCrossSocket::getClientHost() error: "); |
|||
return false; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
setError(error, notConnected, "BaseCrossSocket::getClientHost() - No connection"); |
|||
return false; |
|||
} |
|||
|
|||
noError(error); |
|||
return true; |
|||
} |
|||
|
|||
void BaseCrossSocket::reset() |
|||
{ |
|||
_closeSignal = false; |
|||
} |
|||
|
|||
bool BaseCrossSocket::waitIO(ioTypeEnum &type, CrossSocketErrors *error) |
|||
{ |
|||
if (_blockingMode != blocking) |
|||
{ |
|||
noError(error); |
|||
return true; |
|||
} |
|||
|
|||
// Wait with select() even if no timeout is set
|
|||
|
|||
timeval time; |
|||
timeval *timeForever = NULL; // Forever waiting
|
|||
time.tv_sec = _timeoutSeconds; |
|||
time.tv_usec = _timeoutMicroSeconds; |
|||
|
|||
if (_timeoutSeconds > 0 || _timeoutMicroSeconds > 0) |
|||
{ |
|||
timeForever = &time; |
|||
} |
|||
|
|||
fd_set readFileDescriptorSet; |
|||
fd_set writeFileDescriptorSet; |
|||
fd_set exceptionFileDescriptorSet; |
|||
|
|||
FD_ZERO (&readFileDescriptorSet); |
|||
FD_ZERO (&writeFileDescriptorSet); |
|||
FD_ZERO (&exceptionFileDescriptorSet); |
|||
FD_SET (_socketHandle, &readFileDescriptorSet); |
|||
FD_SET (_socketHandle, &writeFileDescriptorSet); |
|||
FD_SET (_socketHandle, &exceptionFileDescriptorSet); |
|||
|
|||
int returnValue = 0; |
|||
|
|||
switch (type) |
|||
{ |
|||
case ioread: |
|||
returnValue = select(_socketHandle+1, &readFileDescriptorSet, NULL, NULL, timeForever); |
|||
break; |
|||
case iowrite: |
|||
returnValue = select(_socketHandle+1, NULL, &writeFileDescriptorSet, NULL, timeForever); |
|||
break; |
|||
case ioexception: |
|||
returnValue = select(_socketHandle+1, NULL, NULL, &exceptionFileDescriptorSet, timeForever); |
|||
break; |
|||
case ioreadWrite: |
|||
returnValue = select(_socketHandle+1, &readFileDescriptorSet, &writeFileDescriptorSet, NULL, timeForever); |
|||
break; |
|||
case ioall: |
|||
returnValue = select(_socketHandle+1, &readFileDescriptorSet, &writeFileDescriptorSet, &exceptionFileDescriptorSet, timeForever); |
|||
break; |
|||
} |
|||
|
|||
if (returnValue == 0) |
|||
{ |
|||
setError(error, timeout, "BaseCrossSocket::waitIO() timeout"); |
|||
return false; |
|||
} |
|||
else if (returnValue < 0) |
|||
{ |
|||
handleError(error, "BaseCrossSocket::waitIO() error: "); |
|||
return false; |
|||
} |
|||
|
|||
if (FD_ISSET(_socketHandle, &readFileDescriptorSet)) |
|||
{ |
|||
noError(error); |
|||
type = ioread; |
|||
return true; |
|||
} |
|||
|
|||
if (FD_ISSET(_socketHandle, &writeFileDescriptorSet)) |
|||
{ |
|||
noError(error); |
|||
type = iowrite; |
|||
return true; |
|||
} |
|||
|
|||
if (FD_ISSET(_socketHandle, &exceptionFileDescriptorSet)) |
|||
{ |
|||
noError(error); |
|||
type = ioexception; |
|||
return true; |
|||
} |
|||
|
|||
setError(error, fatal, "BaseCrossSocket::waitIO() failed on select()"); |
|||
return false; |
|||
} |
|||
|
|||
bool BaseCrossSocket::waitRead(CrossSocketErrors *error) |
|||
{ |
|||
ioTypeEnum temp = ioread; |
|||
return waitIO(temp, error); |
|||
} |
|||
|
|||
bool BaseCrossSocket::waitWrite(CrossSocketErrors *error) |
|||
{ |
|||
ioTypeEnum temp = iowrite; |
|||
return waitIO(temp, error); |
|||
} |
|||
|
|||
string BaseCrossSocket::getError() |
|||
{ |
|||
return _error; |
|||
} |
|||
|
|||
void BaseCrossSocket::printError() |
|||
{ |
|||
if (_error.size() > 0) |
|||
{ |
|||
fprintf(stderr, "CrossSocket error:\n%s!\n", _error.data()); |
|||
} |
|||
} |
|||
|
|||
void BaseCrossSocket::handleError(CrossSocketErrors *error, string message) |
|||
{ |
|||
#ifdef __WIN32__ |
|||
// Winsock2 errorList (taken from winsock2.h)
|
|||
switch (WSAGetLastError()) |
|||
{ |
|||
case 0: message += "No error"; break; |
|||
case WSAEINTR: message += "Interrupted system call"; break; |
|||
case WSAEBADF: message += "Bad file number"; break; |
|||
case WSAEACCES: message += "Permission denied"; break; |
|||
case WSAEFAULT: message += "Bad address"; break; |
|||
case WSAEINVAL: message += "Invalid argument"; break; |
|||
case WSAEMFILE: message += "Too many open sockets"; break; |
|||
case WSAEWOULDBLOCK: message += "Operation would block"; break; |
|||
case WSAEINPROGRESS: message += "Operation now in progress"; break; |
|||
case WSAEALREADY: message += "Operation already in progress"; break; |
|||
case WSAENOTSOCK: message += "Socket operation on non-socket"; break; |
|||
case WSAEDESTADDRREQ: message += "Destination address required"; break; |
|||
case WSAEMSGSIZE: message += "Message too long"; break; |
|||
case WSAEPROTOTYPE: message += "Protocol wrong type for socket"; break; |
|||
case WSAENOPROTOOPT: message += "Bad protocol option"; break; |
|||
case WSAEPROTONOSUPPORT: message += "Protocol not supported"; break; |
|||
case WSAESOCKTNOSUPPORT: message += "Socket type not supported"; break; |
|||
case WSAEOPNOTSUPP: message += "Operation not supported on socket"; break; |
|||
case WSAEPFNOSUPPORT: message += "Protocol family not supported"; break; |
|||
case WSAEAFNOSUPPORT: message += "Address family not supported"; break; |
|||
case WSAEADDRINUSE: message += "Address already in use"; break; |
|||
case WSAEADDRNOTAVAIL: message += "Can't assign requested address"; break; |
|||
case WSAENETDOWN: message += "Network is down"; break; |
|||
case WSAENETUNREACH: message += "Network is unreachable"; break; |
|||
case WSAENETRESET: message += "Net connection reset"; break; |
|||
case WSAECONNABORTED: message += "Software caused connection abort"; break; |
|||
case WSAECONNRESET: message += "Connection reset by client"; break; |
|||
case WSAENOBUFS: message += "No buffer space available"; break; |
|||
case WSAEISCONN: message += "Socket is already connected"; break; |
|||
case WSAENOTCONN: message += "Socket is not connected"; break; |
|||
case WSAESHUTDOWN: message += "Can't send after socket shutdown"; break; |
|||
case WSAETOOMANYREFS: message += "Too many references"; break; |
|||
case WSAETIMEDOUT: message += "Connection timed out"; break; |
|||
case WSAECONNREFUSED: message += "Connection refused"; break; |
|||
case WSAELOOP: message += "Too many levels of symbolic links"; break; |
|||
case WSAENAMETOOLONG: message += "File name too long"; break; |
|||
case WSAEHOSTDOWN: message += "Host is down"; break; |
|||
case WSAEHOSTUNREACH: message += "No route to host"; break; |
|||
case WSAENOTEMPTY: message += "Directory not empty"; break; |
|||
case WSAEPROCLIM: message += "Too many processes"; break; |
|||
case WSAEUSERS: message += "Too many users"; break; |
|||
case WSAEDQUOT: message += "Disc quota exceeded"; break; |
|||
case WSAESTALE: message += "Stale NFS file handle"; break; |
|||
case WSAEREMOTE: message += "Too many levels of remote in path"; break; |
|||
case WSASYSNOTREADY: message += "Network system is unavailable"; break; |
|||
case WSAVERNOTSUPPORTED: message += "Winsock version out of range"; break; |
|||
case WSANOTINITIALISED: message += "WSAStartup not yet called"; break; |
|||
case WSAEDISCON: message += "Graceful shutdown in progress"; break; |
|||
case WSAHOST_NOT_FOUND: message += "Host not found"; break; |
|||
case WSANO_DATA: message += "No host data of that type was found"; break; |
|||
default: message += "Unknown Winsock error: " + WSAGetLastError(); break; |
|||
} |
|||
#else |
|||
message += strerror(errno); |
|||
#endif |
|||
|
|||
int errorNumber; |
|||
|
|||
#ifdef __WIN32__ |
|||
errorNumber = WSAGetLastError(); |
|||
#else |
|||
errorNumber = errno; |
|||
#endif |
|||
|
|||
CrossSocketErrorsEnum errorMessage; |
|||
|
|||
if (errorNumber == EADDRINUSE) |
|||
{ |
|||
errorMessage = portInUse; |
|||
} |
|||
else if (errorNumber == EAGAIN || errorNumber == EWOULDBLOCK) |
|||
{ |
|||
errorMessage = notReady; |
|||
} |
|||
else if (errorNumber == EMSGSIZE) |
|||
{ |
|||
errorMessage = messageTooLong; |
|||
} |
|||
else if (errorNumber == EINPROGRESS || errorNumber == EALREADY) |
|||
{ |
|||
errorMessage = notReady; |
|||
} |
|||
else if (errorNumber == ECONNREFUSED || errorNumber == ETIMEDOUT) |
|||
{ |
|||
errorMessage = noResponse; |
|||
} |
|||
else if (errorNumber == ENOTCONN || errorNumber == EBADF || errorNumber == ENOTSOCK) |
|||
{ |
|||
errorMessage = notConnected; |
|||
} |
|||
else if (errorNumber == EPIPE) |
|||
{ |
|||
errorMessage = terminated; |
|||
_closeSignal = true; |
|||
} |
|||
else if (errorNumber == EINTR) |
|||
{ |
|||
errorMessage = interrupted; |
|||
} |
|||
else |
|||
{ |
|||
errorMessage = fatal; //default
|
|||
} |
|||
|
|||
setError(error, errorMessage, message); |
|||
} |
|||
|
|||
void BaseCrossSocket::noError(CrossSocketErrors *error) |
|||
{ |
|||
if (error != NULL) |
|||
{ |
|||
*error = ok; |
|||
error->_error = ""; |
|||
error->failed_class = NULL; |
|||
} |
|||
} |
|||
|
|||
void BaseCrossSocket::setError(CrossSocketErrors *error, CrossSocketErrors name, string message) |
|||
{ |
|||
_error = message; |
|||
|
|||
if (error != NULL) |
|||
{ |
|||
*error = name; |
|||
error->_error = message; |
|||
error->failed_class = this; |
|||
} |
|||
else |
|||
{ |
|||
if (ERRORMODE == 0) |
|||
{ |
|||
printError(); |
|||
if (name == terminated) |
|||
{ |
|||
disconnect(); |
|||
} |
|||
} |
|||
else if (ERRORMODE == 1) |
|||
{ |
|||
// Reset the state
|
|||
reset(); |
|||
|
|||
close(_socketHandle); |
|||
_socketHandle = -1; |
|||
|
|||
CrossSocketErrors crossSocketError; |
|||
crossSocketError = name; |
|||
crossSocketError._error = message; |
|||
crossSocketError.failed_class = this; |
|||
throw crossSocketError; |
|||
} |
|||
else |
|||
{ |
|||
exit(-1); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,107 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// BaseCrossSocket.h
|
|||
|
|||
#pragma once |
|||
|
|||
#include "CrossSocketsCore.h" |
|||
#include "CrossSocketConfig.h" |
|||
#include "CrossSocketErrors.h" |
|||
|
|||
#include <unistd.h> |
|||
#include <string> |
|||
|
|||
class CrossThreadsHandler; |
|||
class CrossSocket; |
|||
|
|||
class BaseCrossSocket |
|||
{ |
|||
public: |
|||
BaseCrossSocket(); |
|||
virtual ~BaseCrossSocket(); |
|||
|
|||
// Blocking : Everything blocks until operation is done
|
|||
// noWait : First call time blocking only
|
|||
// nonBlocking : Allow everything simultaneously
|
|||
enum blockTypeEnum |
|||
{ |
|||
blocking, |
|||
noWait, |
|||
nonblocking |
|||
}; |
|||
|
|||
// wait for I/O (with timeout)
|
|||
enum ioTypeEnum |
|||
{ |
|||
ioread, |
|||
iowrite, |
|||
ioexception, |
|||
ioreadWrite, |
|||
ioall |
|||
}; |
|||
|
|||
virtual bool listen(int connectionLimit = 5, CrossSocketErrors* = NULL); |
|||
virtual BaseCrossSocket* accept(CrossSocketErrors* = NULL); |
|||
|
|||
virtual bool isConnected(); |
|||
virtual bool disconnect(CrossSocketErrors* = NULL); |
|||
virtual bool checkPassword(BaseCrossSocket *socket); |
|||
|
|||
// force to close the socket
|
|||
virtual bool closeSocketHandle(); |
|||
|
|||
virtual int write(const std::string message, CrossSocketErrors *error = NULL); |
|||
virtual int write(const std::string message, size_t length, CrossSocketErrors *error = NULL); |
|||
virtual int writeLine(std::string message, CrossSocketErrors *error = NULL); |
|||
virtual int writeLine(std::string message, size_t length, CrossSocketErrors *error = NULL); |
|||
virtual ssize_t read(char *buffer, int bytes, CrossSocketErrors *error = NULL); |
|||
virtual ssize_t read(char *buffer, CrossSocketErrors *error = NULL); |
|||
virtual ssize_t readLine(char *buffer, int bytes, CrossSocketErrors *error = NULL); |
|||
virtual std::string readLine(int size, CrossSocketErrors *error = NULL); |
|||
virtual void setPassword(const std::string password); |
|||
|
|||
virtual int getClientSocket(CrossSocketErrors *error); |
|||
virtual bool getServerHost(sockaddr *host, CrossSocketErrors *error = NULL); |
|||
virtual bool getClientHost(sockaddr *client, CrossSocketErrors *error = NULL); |
|||
|
|||
// Receive timeout (can only be used in blocking mode)
|
|||
void setTimeout(unsigned int seconds, unsigned int miliseconds); |
|||
|
|||
// Error handling
|
|||
virtual void printError(); |
|||
virtual std::string getError(); |
|||
|
|||
protected: |
|||
virtual void getSocket() = 0; |
|||
virtual BaseCrossSocket* create(int socketdescriptor, CrossSocketErrors *error) = 0; |
|||
virtual void reset(); |
|||
|
|||
virtual bool waitIO(ioTypeEnum &type, CrossSocketErrors *error); |
|||
bool waitRead(CrossSocketErrors *error); |
|||
bool waitWrite(CrossSocketErrors *error); |
|||
|
|||
virtual void handleError(CrossSocketErrors *error, std::string message); |
|||
virtual void noError(CrossSocketErrors *error); |
|||
virtual void setError(CrossSocketErrors *error, CrossSocketErrors name, std::string message); |
|||
|
|||
int _socketHandle; |
|||
std::string _password; |
|||
|
|||
BaseCrossSocket *_clientSocket; |
|||
|
|||
// last error
|
|||
std::string _error; |
|||
|
|||
// have we received a shutdown signal?
|
|||
bool _closeSignal; |
|||
|
|||
// blocking mode
|
|||
blockTypeEnum _blockingMode; |
|||
|
|||
CrossThreadsHandler *_threadHandler; |
|||
|
|||
// timeout for waitIO()
|
|||
int _timeoutSeconds; |
|||
int _timeoutMicroSeconds; |
|||
}; |
@ -0,0 +1,252 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// CrossSocket.cpp
|
|||
|
|||
#include "CrossSocket.h" |
|||
|
|||
#ifndef __WIN32__ |
|||
#include <netdb.h> |
|||
#include <arpa/inet.h> |
|||
#include <fcntl.h> |
|||
#include <sys/select.h> |
|||
#include <sys/time.h> |
|||
#else |
|||
#define F_SETFL FIONBIO |
|||
#define O_NONBLOCK 1 |
|||
|
|||
extern int close(int fd); |
|||
extern int fcntl(int fd, int cmd, long arg); |
|||
#endif |
|||
|
|||
using namespace std; |
|||
|
|||
CrossSocket::CrossSocket(blockTypeEnum block) |
|||
{ |
|||
_blockingMode = block; |
|||
} |
|||
|
|||
CrossSocket::~CrossSocket() |
|||
{ |
|||
|
|||
} |
|||
|
|||
void CrossSocket::getSocket() |
|||
{ |
|||
if (_socketHandle < 0) |
|||
{ |
|||
_socketHandle = socket(PF_INET, SOCK_STREAM, 0); |
|||
|
|||
if (_blockingMode == nonblocking) |
|||
{ |
|||
fcntl(_socketHandle, F_SETFL, O_NONBLOCK); |
|||
} |
|||
|
|||
//reset state
|
|||
reset(); |
|||
} |
|||
} |
|||
|
|||
BaseCrossSocket* CrossSocket::create(int socketdescriptor, CrossSocketErrors *error) |
|||
{ |
|||
CrossSocket* remoteClass; |
|||
|
|||
remoteClass = new CrossSocket(_blockingMode); |
|||
remoteClass->_socketHandle = socketdescriptor; |
|||
|
|||
noError(error); |
|||
return remoteClass; |
|||
} |
|||
|
|||
bool CrossSocket::bind(int port, CrossSocketErrors *error) |
|||
{ |
|||
return bind(port, "", error); |
|||
} |
|||
|
|||
bool CrossSocket::bind(int port, string host, CrossSocketErrors *error) |
|||
{ |
|||
hostent *hostEntry; |
|||
in_addr networkAddress; |
|||
|
|||
if (host.size() > 0 ) |
|||
{ |
|||
// Bind to a specific address
|
|||
|
|||
if ((hostEntry = gethostbyname(host.data())) == NULL) |
|||
{ |
|||
setError(error, fatal, "CrossSocket::bind() - Can't get host by name"); |
|||
return false; |
|||
} |
|||
|
|||
networkAddress = *((in_addr *)hostEntry->h_addr); |
|||
} |
|||
else |
|||
{ |
|||
// Bind to any address
|
|||
networkAddress.s_addr = INADDR_ANY; |
|||
} |
|||
|
|||
getSocket(); |
|||
|
|||
sockaddr_in serverAddress; |
|||
|
|||
memset(&serverAddress, 0, sizeof(serverAddress)); |
|||
serverAddress.sin_family = AF_INET; |
|||
serverAddress.sin_port = htons(port); |
|||
serverAddress.sin_addr.s_addr = networkAddress.s_addr; |
|||
|
|||
if (::bind(_socketHandle, (sockaddr *)&serverAddress, sizeof(serverAddress)) == -1) |
|||
{ |
|||
handleError(error, "CrossSocket::bind() error: "); |
|||
return false; |
|||
} |
|||
|
|||
noError(error); |
|||
return true; |
|||
} |
|||
|
|||
bool CrossSocket::connect(int port, string hostname, CrossSocketErrors *error) |
|||
{ |
|||
getSocket(); |
|||
|
|||
hostent *host; |
|||
|
|||
if ((host = gethostbyname(hostname.data())) == NULL ) |
|||
{ |
|||
setError(error, fatal, "CrossSocket::connect() - Can't get host by name"); |
|||
return false; |
|||
} |
|||
|
|||
sockaddr_in clientAddress; |
|||
|
|||
memset(&clientAddress, 0, sizeof(clientAddress)); |
|||
clientAddress.sin_family = AF_INET; |
|||
clientAddress.sin_port = htons(port); |
|||
clientAddress.sin_addr = *((in_addr *)host->h_addr); |
|||
|
|||
if (::connect(_socketHandle, (sockaddr *)&clientAddress, sizeof(clientAddress)) == -1) |
|||
{ |
|||
handleError(error, "CrossSocket::connect() error: "); |
|||
return false; |
|||
} |
|||
|
|||
noError(error); |
|||
return true; |
|||
} |
|||
|
|||
|
|||
string CrossSocket::getClientAddress(CrossSocketErrors *error) |
|||
{ |
|||
sockaddr_in clientAddress; |
|||
|
|||
if (!getClientHost((sockaddr *)&clientAddress, error)) |
|||
{ |
|||
return ""; |
|||
} |
|||
|
|||
char *addressPointer; |
|||
|
|||
if ((addressPointer = inet_ntoa(clientAddress.sin_addr)) == NULL ) |
|||
{ |
|||
setError(error, fatal, "CrossSocket::getClientHostName() - Can't get client address"); |
|||
return ""; |
|||
} |
|||
|
|||
noError(error); |
|||
return string (addressPointer); |
|||
} |
|||
|
|||
int CrossSocket::getClientPort(CrossSocketErrors *error) |
|||
{ |
|||
sockaddr_in clientAddress; |
|||
|
|||
if (!getClientHost((sockaddr *)&clientAddress, error)) |
|||
{ |
|||
return -1; |
|||
} |
|||
|
|||
noError(error); |
|||
|
|||
return ntohs(clientAddress.sin_port); |
|||
} |
|||
|
|||
string CrossSocket::getClientHostName(CrossSocketErrors *error) |
|||
{ |
|||
string name = getClientAddress(error); |
|||
|
|||
if (name.size() < 1) |
|||
{ |
|||
return ""; |
|||
} |
|||
|
|||
hostent *host; |
|||
|
|||
if ((host = gethostbyname(name.data())) == NULL ) |
|||
{ |
|||
setError(error, fatal, "CrossSocket::getClientHostName() - Can't get client by address"); |
|||
return ""; |
|||
} |
|||
|
|||
noError(error); |
|||
return string(host->h_name);; |
|||
} |
|||
|
|||
string CrossSocket::getServerAddress(CrossSocketErrors *error) |
|||
{ |
|||
//We need to get the real address, so we must
|
|||
//first get this computers host name and then
|
|||
//translate that into an address!
|
|||
|
|||
string name = getServerHostName(error); |
|||
if (name.size() < 1) |
|||
{ |
|||
return ""; |
|||
} |
|||
|
|||
hostent *host; |
|||
|
|||
if ((host = gethostbyname(name.data())) == NULL ) |
|||
{ |
|||
setError(error, fatal, "CrossSocket::getServerAddress() - Can't get host by name"); |
|||
return ""; |
|||
} |
|||
|
|||
char *addressPointer; |
|||
|
|||
if ((addressPointer = inet_ntoa(*((in_addr *)host->h_addr))) == NULL) |
|||
{ |
|||
setError(error, fatal, "CrossSocket::getServerAddress() - Can't get host address"); |
|||
return ""; |
|||
} |
|||
return string(addressPointer); |
|||
} |
|||
|
|||
int CrossSocket::getServerPort(CrossSocketErrors *error) |
|||
{ |
|||
sockaddr_in address; |
|||
|
|||
if (!getServerHost((sockaddr *)&address, error)) |
|||
{ |
|||
return -1; |
|||
} |
|||
|
|||
noError(error); |
|||
|
|||
return ntohs(address.sin_port); |
|||
} |
|||
|
|||
string CrossSocket::getServerHostName(CrossSocketErrors *error) |
|||
{ |
|||
char buffer[256]; |
|||
|
|||
if (gethostname(buffer, 256) != 0) |
|||
{ |
|||
handleError(error, "CrossSocket::gethostname() error: "); |
|||
return ""; |
|||
} |
|||
|
|||
string message(buffer); |
|||
|
|||
noError(error); |
|||
return message; |
|||
} |
@ -0,0 +1,34 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// CrossSocket.h
|
|||
|
|||
#pragma once |
|||
|
|||
#include "CrossSocketsCore.h" |
|||
#include "BaseCrossSocket.h" |
|||
#include <string> |
|||
|
|||
class CrossSocket : public BaseCrossSocket |
|||
{ |
|||
public: |
|||
CrossSocket(blockTypeEnum block = blocking); |
|||
virtual ~CrossSocket(); |
|||
|
|||
virtual bool bind(int port, CrossSocketErrors *error = NULL); //use port=0 to get any free port
|
|||
virtual bool bind(int port, std::string host, CrossSocketErrors *error = NULL); //you can also specify the host interface to use
|
|||
virtual bool connect(int port, std::string hostname, CrossSocketErrors *error = NULL); |
|||
|
|||
// Tools
|
|||
// Gets IP address, name or port.
|
|||
virtual std::string getClientAddress(CrossSocketErrors *error = NULL); |
|||
virtual int getClientPort(CrossSocketErrors *error = NULL); |
|||
virtual std::string getClientHostName(CrossSocketErrors *error = NULL); |
|||
virtual std::string getServerAddress(CrossSocketErrors *error = NULL); |
|||
virtual int getServerPort(CrossSocketErrors *error = NULL); |
|||
virtual std::string getServerHostName(CrossSocketErrors *error = NULL); |
|||
|
|||
protected: |
|||
virtual void getSocket(); |
|||
virtual BaseCrossSocket* create(int socketdescriptor, CrossSocketErrors *error); |
|||
}; |
@ -0,0 +1,9 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// CrossSocketConfig.h
|
|||
|
|||
#pragma once |
|||
|
|||
// Set the errorMode (0: Verbose error 1: Throw error)
|
|||
#define ERRORMODE 0 |
@ -0,0 +1,52 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// CrossSocketErrors.cpp
|
|||
|
|||
#include "BaseCrossSocket.h" |
|||
|
|||
using namespace std; |
|||
|
|||
CrossSocketErrors::CrossSocketErrors() |
|||
{ |
|||
be = ok; |
|||
_error = ""; |
|||
failed_class = NULL; |
|||
} |
|||
|
|||
CrossSocketErrors::CrossSocketErrors(CrossSocketErrorsEnum e) |
|||
{ |
|||
be = e; |
|||
_error = ""; |
|||
failed_class = NULL; |
|||
} |
|||
|
|||
string CrossSocketErrors::getError() |
|||
{ |
|||
return _error; |
|||
} |
|||
|
|||
BaseCrossSocket* CrossSocketErrors::getFailedClass(void) |
|||
{ |
|||
return failed_class; |
|||
} |
|||
|
|||
void CrossSocketErrors::setErrorString(string msg) |
|||
{ |
|||
_error = msg; |
|||
} |
|||
|
|||
void CrossSocketErrors::setFailedClass(BaseCrossSocket *pnt) |
|||
{ |
|||
failed_class = pnt; |
|||
} |
|||
|
|||
bool CrossSocketErrors::operator==(CrossSocketErrors e) |
|||
{ |
|||
return be == e.be; |
|||
} |
|||
|
|||
bool CrossSocketErrors::operator!=(CrossSocketErrors e) |
|||
{ |
|||
return be != e.be; |
|||
} |
@ -0,0 +1,53 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// CrossSocketErrors.h
|
|||
|
|||
#pragma once |
|||
|
|||
#include <string> |
|||
|
|||
enum CrossSocketErrorsEnum |
|||
{ |
|||
ok, // Operation successful
|
|||
fatal, // Unspecified error
|
|||
notReady, // The socket was not ready (blockMode)
|
|||
portInUse, // The specified port is already in use
|
|||
notConnected, // The socket is invalid or not connected
|
|||
messageTooLong, // The messageSize is too big to be send
|
|||
terminated, // Connection terminated (by client)
|
|||
noResponse, // Cannot connect to client
|
|||
timeout, // Read/Write operation timeout occurred (in blockingMode)
|
|||
interrupted // Operation was blocked by signal
|
|||
}; |
|||
|
|||
class BaseCrossSocket; |
|||
|
|||
class CrossSocketErrors |
|||
{ |
|||
public: |
|||
CrossSocketErrors(); |
|||
CrossSocketErrors(CrossSocketErrorsEnum e); |
|||
|
|||
virtual ~CrossSocketErrors(){;} |
|||
|
|||
virtual std::string getError(); |
|||
virtual BaseCrossSocket* getFailedClass(void); |
|||
|
|||
virtual bool operator == (CrossSocketErrors e); |
|||
virtual bool operator != (CrossSocketErrors e); |
|||
|
|||
virtual void setErrorString(std::string msg); |
|||
virtual void setFailedClass(BaseCrossSocket *pnt); |
|||
protected: |
|||
friend class BaseCrossSocket; |
|||
|
|||
// The base error type
|
|||
CrossSocketErrorsEnum be; |
|||
|
|||
// Human readable error string
|
|||
std::string _error; |
|||
|
|||
// A pointer to the class causing the error
|
|||
BaseCrossSocket *failed_class; |
|||
}; |
@ -0,0 +1,62 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// CrossSocketPlatform.h
|
|||
|
|||
#ifdef __WIN32__ |
|||
// Define the errorCodes for the Windows platform (taken from CYGWIN error numbers)
|
|||
#define EOPNOTSUPP WSAEOPNOTSUPP |
|||
#define EINTR WSAEINTR |
|||
#define EADDRINUSE WSAEADDRINUSE |
|||
#define EINPROGRESS WSAEINPROGRESS |
|||
#define EWOULDBLOCK WSAEWOULDBLOCK |
|||
#define ENOTSOCK WSAENOTSOCK |
|||
#define EMSGSIZE WSAEMSGSIZE |
|||
#define ETIMEDOUT WSAETIMEDOUT |
|||
#define EALREADY WSAEALREADY |
|||
#define EBADF WSAEBADF |
|||
#define ECONNREFUSED WSAECONNREFUSED |
|||
#define ENOTCONN WSAENOTCONN |
|||
#else |
|||
#include <netdb.h> |
|||
#include <arpa/inet.h> |
|||
#include <fcntl.h> |
|||
#include <sys/select.h> |
|||
#include <sys/time.h> |
|||
#include <sstream> |
|||
|
|||
#define SOCKETFAIL -1 |
|||
#endif |
|||
|
|||
#ifndef MSG_NOSIGNAL |
|||
#define MSG_NOSIGNAL 0 |
|||
#endif |
|||
|
|||
// Redefine the socklen_t parameter because it is different on Windows
|
|||
#ifdef __WIN32__ |
|||
#define sw_socklen_t int |
|||
#else |
|||
#define sw_socklen_t socklen_t |
|||
#endif |
|||
|
|||
using namespace std; |
|||
|
|||
#ifdef __WIN32__ |
|||
|
|||
int fcntl(int fd, int cmd, long arg) |
|||
{ |
|||
unsigned long mode = arg; |
|||
|
|||
return WSAIoctl(fd, cmd, &mode, sizeof(unsigned long), NULL, 0, NULL, NULL, NULL); |
|||
} |
|||
|
|||
int close(int fd) |
|||
{ |
|||
return closesocket(fd); |
|||
} |
|||
|
|||
void WSA_exit(void) |
|||
{ |
|||
WSACleanup(); |
|||
} |
|||
#endif |
@ -0,0 +1,9 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// CrossSockets.h
|
|||
|
|||
#pragma once |
|||
|
|||
#include "BaseCrossSocket.h" |
|||
#include "CrossSocket.h" |
@ -0,0 +1,18 @@ |
|||
// CrossSockets
|
|||
// Copyright Jeroen Saey
|
|||
// Created 27-01-2013
|
|||
// CrossSocketsCore.h
|
|||
|
|||
#pragma once |
|||
|
|||
#ifdef __WIN32__ |
|||
#include <winsock2.h> |
|||
|
|||
#define F_SETFL FIONBIO |
|||
#define O_NONBLOCK 1 |
|||
#else |
|||
#include <sys/types.h> |
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include <sys/un.h> |
|||
#endif |
Binary file not shown.
@ -0,0 +1,109 @@ |
|||
// CrossThreads
|
|||
// Copyright Jeroen Saey
|
|||
// Created 29-01-2013
|
|||
// CrossThread.cpp
|
|||
|
|||
#include "CrossThreads.h" |
|||
#include "errno.h" |
|||
#include <iostream> |
|||
|
|||
CrossThreads::CrossThreads(threadCallBack callBack, long timeout) : _callBack(callBack), _threadID(0) |
|||
#ifdef __WIN32__ |
|||
, _timeout(timeout) , _thread(NULL) |
|||
#endif |
|||
{ |
|||
} |
|||
|
|||
CrossThreads::~CrossThreads() |
|||
{ |
|||
stop(); |
|||
} |
|||
|
|||
void CrossThreads::stop() |
|||
{ |
|||
#ifdef __WIN32__ |
|||
//waiting for the thread to terminate
|
|||
if (_thread) |
|||
{ |
|||
if (WAIT_TIMEOUT == ::WaitForSingleObject (_thread, _timeout)) |
|||
::TerminateThread (_thread, 1); |
|||
|
|||
::CloseHandle (_thread); |
|||
} |
|||
#endif |
|||
} |
|||
|
|||
int CrossThreads::create() |
|||
{ |
|||
|
|||
#ifdef __WIN32__ |
|||
_thread = ::CreateThread (NULL, 0, |
|||
(unsigned long (__stdcall *)(void *))_callBack, |
|||
NULL, 0, &_thread); |
|||
if (NULL == _thread) |
|||
{ |
|||
break; |
|||
} |
|||
#endif |
|||
|
|||
pthread_attr_t attribute; |
|||
|
|||
// Initialize and set thread and set the attribute
|
|||
pthread_attr_init(&attribute); |
|||
pthread_attr_setdetachstate(&attribute, PTHREAD_CREATE_DETACHED); |
|||
|
|||
int result; |
|||
do |
|||
{ |
|||
result = pthread_create(&_threadID, &attribute, _callBack, (void *)this); |
|||
} while (false); |
|||
|
|||
if (result != 0) |
|||
{ |
|||
std::cout << "CrossThread: Failed to create the thread\n"; |
|||
if (result == EAGAIN) |
|||
{ |
|||
std::cout << "The system lacked the necessary resource to create another thread"; |
|||
} |
|||
else if (result == EINVAL) |
|||
{ |
|||
std::cout << "CrossThread: The value given in the arguments is invalid!"; |
|||
} |
|||
else |
|||
{ |
|||
std::cout << "CrossThread: The caller does not have the appropriate rights"; |
|||
} |
|||
} |
|||
|
|||
// Free the attributes of the thread
|
|||
pthread_attr_destroy(&attribute); |
|||
return result; |
|||
} |
|||
|
|||
void CrossThreads::join() |
|||
{ |
|||
if (0 != pthread_join(_threadID, NULL)) |
|||
{ |
|||
fprintf(stderr, "pthread_join error\n"); |
|||
} |
|||
} |
|||
|
|||
int CrossThreads::remove() |
|||
{ |
|||
return pthread_detach(_threadID); |
|||
} |
|||
|
|||
unsigned long CrossThreads::getThreadID() |
|||
{ |
|||
return printf("%lu\n", (unsigned long) _threadID); |
|||
} |
|||
|
|||
void CrossThreads::setThreadCallback(threadCallBack callBack) |
|||
{ |
|||
_callBack = callBack; |
|||
} |
|||
|
|||
bool CrossThreads::isCreated() |
|||
{ |
|||
return _threadID ? true : false; |
|||
} |
@ -0,0 +1,47 @@ |
|||
// CrossThreads
|
|||
// Copyright Jeroen Saey
|
|||
// Created 29-01-2013
|
|||
// CrossThreads.h
|
|||
|
|||
#pragma once |
|||
|
|||
#ifndef __WIN32__ |
|||
|
|||
#include "pthread.h" |
|||
|
|||
typedef pthread_t threadID; |
|||
typedef void* (*threadCallBack)(void* parameter); |
|||
|
|||
#else |
|||
|
|||
#include <windows.h> |
|||
typedef unsigned long (*threadCallBack)(void* parameter); |
|||
typedef DWORD threadID; |
|||
|
|||
#endif |
|||
|
|||
class CrossThreads |
|||
{ |
|||
public: |
|||
|
|||
CrossThreads(threadCallBack callBack = NULL, long timeout = 3000); |
|||
virtual ~CrossThreads(); |
|||
|
|||
void setThreadCallback(threadCallBack callBack); |
|||
unsigned long getThreadID(); |
|||
int create(); |
|||
int remove(); |
|||
void join(); |
|||
bool isCreated(); |
|||
|
|||
private: |
|||
threadID _threadID; |
|||
threadCallBack _callBack; |
|||
|
|||
#ifdef __WIN32__ |
|||
long _timeout; |
|||
HANDLE _thread; |
|||
#endif |
|||
|
|||
void stop(); |
|||
}; |
@ -0,0 +1,58 @@ |
|||
// CrossThreadsHandler
|
|||
// Copyright Jeroen Saey
|
|||
// Created 29-01-2013
|
|||
// CrossThreadsHandler.cpp
|
|||
|
|||
#include "CrossThreadsHandler.h" |
|||
|
|||
#include <sstream> |
|||
#include <iostream> |
|||
#include <errno.h> |
|||
|
|||
using namespace std; |
|||
|
|||
CrossThreadsHandler::CrossThreadsHandler() |
|||
{ |
|||
} |
|||
|
|||
unsigned long CrossThreadsHandler::createAndStartThread(threadCallBack callback) |
|||
{ |
|||
CrossThreads *thread = new CrossThreads(callback); |
|||
thread->create(); |
|||
_threadList.insert(pair<unsigned long, CrossThreads*>(thread->getThreadID(),thread)); |
|||
return thread->getThreadID(); |
|||
} |
|||
|
|||
bool CrossThreadsHandler::joinThread(unsigned long threadID) |
|||
{ |
|||
map <unsigned long, CrossThreads*>::iterator iterator = _threadList.find(threadID); |
|||
if (iterator != _threadList.end()) |
|||
{ |
|||
iterator->second->join(); |
|||
return true; |
|||
} |
|||
else |
|||
{ |
|||
cout << "The client could not be found in the threadList."; |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
bool CrossThreadsHandler::removeThread(unsigned long threadID) |
|||
{ |
|||
map <unsigned long, CrossThreads*>::iterator iterator = _threadList.find(threadID); |
|||
if (iterator != _threadList.end()) |
|||
{ |
|||
_threadList.erase(iterator); |
|||
return true; |
|||
} |
|||
else |
|||
{ |
|||
cout << "The client could not be found in the threadList."; |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
CrossThreadsHandler::~CrossThreadsHandler() |
|||
{ |
|||
} |
@ -0,0 +1,25 @@ |
|||
// CrossThreadsHandler
|
|||
// Copyright Jeroen Saey
|
|||
// Created 29-01-2013
|
|||
// CrossThreadsHandler.h
|
|||
|
|||
#pragma once |
|||
|
|||
#include "CrossThreads.h" |
|||
|
|||
#include <string> |
|||
#include <map> |
|||
|
|||
class CrossThreadsHandler |
|||
{ |
|||
public: |
|||
CrossThreadsHandler(); |
|||
virtual ~CrossThreadsHandler(); |
|||
|
|||
unsigned long createAndStartThread (threadCallBack callback); |
|||
bool removeThread (unsigned long threadID); |
|||
bool joinThread (unsigned long threadID); |
|||
|
|||
private: |
|||
std::map<unsigned long, CrossThreads*> _threadList; |
|||
}; |
@ -0,0 +1,66 @@ |
|||
/*
|
|||
* File: Server.cpp |
|||
* Author: SuperSmash |
|||
* |
|||
* Created on 15 february 2013, 21:10 |
|||
*/ |
|||
|
|||
#include "Server.h" |
|||
#include "CrossSockets/CrossThreadsHandler.h" |
|||
|
|||
#include <sstream> |
|||
|
|||
using namespace std; |
|||
|
|||
static Server *self; |
|||
|
|||
Server::Server() |
|||
{ |
|||
self = this; |
|||
|
|||
// Setup the listener into listeningMode and define the serverport
|
|||
_server.bind(2013); |
|||
_server.listen(); |
|||
_server.setPassword("welcome"); |
|||
|
|||
stringstream startMessage; |
|||
LogManagement::getInstance()->write(startMessage << "CrossSocket server started.\n" << "PORT: 2013"); |
|||
cout << APPLICATIONNAME << " server started.\n"; |
|||
|
|||
_threadHandler = new CrossThreadsHandler(); |
|||
|
|||
while (_server.isConnected()) |
|||
{ |
|||
listenForConnections((CrossSocket*)_server.accept()); |
|||
} |
|||
} |
|||
|
|||
void Server::listenForConnections(CrossSocket* socket) |
|||
{ |
|||