Initial commit
This commit is contained in:
parent
29d0adaa45
commit
dab50aaf41
|
@ -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)
|
||||||
|
{
|
||||||
|
_clientSocket = socket;
|
||||||
|
stringstream welcomeMessage;
|
||||||
|
welcomeMessage << "Welcome to the CrossSocket server!";
|
||||||
|
socket->writeLine(welcomeMessage.str());
|
||||||
|
_threadID = _threadHandler->createAndStartThread((threadCallBack) &Server::handleLoopCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Server::handleLoopCallback(void *functionPointer)
|
||||||
|
{
|
||||||
|
static_cast <Server*>(functionPointer)->handleLoop(self->_clientSocket, self->_threadID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::handleLoop(CrossSocket *socket, unsigned long threadID)
|
||||||
|
{
|
||||||
|
if (self->_server.checkPassword(socket))
|
||||||
|
{
|
||||||
|
while (socket->isConnected())
|
||||||
|
{
|
||||||
|
// Do something here because we got an active connection to the server using CrossSockets ^^
|
||||||
|
}
|
||||||
|
delete socket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Server::~Server()
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* File: Server.h
|
||||||
|
* Author: SuperSmash
|
||||||
|
*
|
||||||
|
* Created on 15 february 2013, 21:10
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CrossSockets/CrossSockets.h"
|
||||||
|
#include "CrossSockets/CrossThreads.h"
|
||||||
|
|
||||||
|
class CrossThreadsHandler;
|
||||||
|
|
||||||
|
class Server
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Server();
|
||||||
|
virtual ~Server();
|
||||||
|
|
||||||
|
void listenForConnections(CrossSocket* socket);
|
||||||
|
void deleteClientSocketWithForce(int signalnumber);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void* handleLoopCallback(void *functionPointer);
|
||||||
|
void handleLoop(CrossSocket *socket, unsigned long threadID);
|
||||||
|
|
||||||
|
CrossSocket _server;
|
||||||
|
CrossThreadsHandler *_threadHandler;
|
||||||
|
|
||||||
|
CrossSocket *_clientSocket;
|
||||||
|
unsigned long _threadID;
|
||||||
|
};
|
14
README.md
14
README.md
|
@ -1,3 +1,13 @@
|
||||||
# CrossSockets
|
CrossSockets:
|
||||||
|
|
||||||
CrossSockets C++
|
CrossSockets is a library for C++ to work with the POSIX and Winsock2 sockets.
|
||||||
|
CrossSockets can help you implement a network communication application.
|
||||||
|
CrossSockets was created to serve as a client - server communication protocol.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
If the server is running you can establish a connection using putty or any other client.
|
||||||
|
(if you use putty you need to connect to the server using a RAW connection)
|
||||||
|
|
||||||
|
Port: 2013
|
||||||
|
Password: welcome
|
||||||
|
|
Loading…
Reference in New Issue