593 lines
22 KiB
C++
593 lines
22 KiB
C++
#include <iostream>
|
|
#include <pthread.h>
|
|
#include <unistd.h>
|
|
#include <algorithm> /// tD->VectorArray[0].erase(std::remove(tD->VectorArray[0].begin(), tD->VectorArray[0].end(), tD), tD->VectorArray[0].end());
|
|
|
|
#include <vector>
|
|
#include "server_tcp_lib.h"
|
|
|
|
/*Accept Client
|
|
* -> To Thread
|
|
* -> Reczive Data
|
|
* -> Pushback WaitingQueuqVector
|
|
* ->Thread 2: go throu WaitingQueuqVector
|
|
* -> pushback vector_<server/from_server/from_client>
|
|
* -> Check for new Connections(from_server_id == from_client_id)
|
|
* -> if Connecting -> send msg to server ( server_id == from_server_id)
|
|
* ->New Connection: 2 Threads: Redirection: Up,Down -> (pthread_detach???)
|
|
*/
|
|
|
|
struct Client {
|
|
Client()
|
|
: ConnectionsLeft(-1) {}
|
|
CLIENT client;
|
|
int ConnectionsLeft;
|
|
|
|
enum TYPE {
|
|
UNDEFINED = 0,
|
|
SERVER = 1,
|
|
FROM_SERVER_CLIENT_FREE = 2,
|
|
FROM_USER_CLIENT = 3,
|
|
FROM_SERVER_CLIENT_USED = 4,
|
|
UNKNOWN = 5
|
|
} Type;
|
|
|
|
std::string serverID,
|
|
serverPW,
|
|
serverMemAddr;
|
|
};
|
|
|
|
|
|
constexpr unsigned short serverPort = 4000;
|
|
static bool shouldStop = false;
|
|
|
|
static TCP_SERVER server;
|
|
static std::vector < pthread_t > threadList;
|
|
|
|
static std::vector<Client *> VectorArray[5];
|
|
static auto &WaitingQuequeList = VectorArray[0];
|
|
static auto &ServerList = VectorArray[1]; // *---> Pointer auf <Client *>
|
|
static auto &FromServerClientListFree = VectorArray[2];
|
|
static auto &FromUserClientListConnected = VectorArray[3];
|
|
static auto &FromServerClientListConnected = VectorArray[4];
|
|
|
|
/*
|
|
template < typename T>
|
|
int findInVector(const std::vector<T> & vecOfElements, const T & element)
|
|
{
|
|
// Find given element in vector
|
|
auto it = std::find(vecOfElements.begin(), vecOfElements.end(), element);
|
|
return ( it == vecOfElements.end() ) ? -1 : static_cast<int>(distance(vecOfElements.begin(), it));
|
|
}
|
|
*/
|
|
|
|
template < typename T>
|
|
void deleteAndSetToNull(T ** var) {
|
|
if(*var != nullptr)
|
|
/// delete *var;
|
|
perror("DELETE...");
|
|
else
|
|
std::cout << "WARNING: in deleteAndSetToNull: Pointer was null" << std::endl;
|
|
*var = nullptr;
|
|
}
|
|
|
|
|
|
[[ noreturn ]] void pthread_exit_WithRemoveFromThreadList( Client ** toDeleteClient = nullptr ) {
|
|
if(toDeleteClient) {
|
|
std::cout << " -> Delete Client in pthread_exit_With_RemoveFromList(): " << *toDeleteClient << std::endl;
|
|
deleteAndSetToNull(toDeleteClient);
|
|
}
|
|
|
|
auto it = std::find(threadList.begin(), threadList.end(), pthread_self());
|
|
if( it == threadList.end() )
|
|
std::cerr << "WARNUNG: Konnte Thread nicht in threadList finden: " << pthread_self() << std::endl;
|
|
else
|
|
threadList.erase( it );
|
|
|
|
std::cout << " ~~> pthread_exit( " << pthread_self() << " )" << std::endl;
|
|
pthread_exit(nullptr);
|
|
}
|
|
|
|
|
|
struct redirectThreadData
|
|
{
|
|
redirectThreadData(Client ** cli1, Client **cli2)
|
|
: cli1(cli1), cli2(cli2) {}
|
|
Client **cli1, **cli2;
|
|
};
|
|
|
|
|
|
void * closeConnectionWithClient(Client ** client, bool removeFromList = false, std::string DisconnectMsg = "") {
|
|
|
|
if(client == nullptr) {
|
|
std::cerr << "Got invalid client." << std::endl;
|
|
return nullptr;
|
|
} else if (* client == nullptr) {
|
|
std::cerr << "-------> FATAL ERROR: SHOULD DELETE Client A SECOND TIME!!" << std::endl;
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
if(DisconnectMsg != "" && (**client).client.send_(DisconnectMsg.c_str(), DisconnectMsg.length()) != 0)
|
|
std::cout << "Warning: Send failed in closeConnectionWithClient(): " << (**client).client.getLastError() << std::endl;
|
|
|
|
if(removeFromList && ( ((**client).Type == Client::SERVER) || ((**client).Type == Client::FROM_SERVER_CLIENT_FREE) || ((**client).Type == Client::FROM_SERVER_CLIENT_USED) || ((**client).Type == Client::FROM_USER_CLIENT) )) {
|
|
auto it = std::find(VectorArray[(**client).Type].begin(), VectorArray[(**client).Type].end(), *client);
|
|
if( it == VectorArray[(**client).Type].end() )
|
|
std::cerr << "Error: Couldn't find client in RemoveFromList: " << *client << std::endl;
|
|
else {
|
|
std::cout << "Remove Client ( " << (*client) << " ) in Vector: " << *it.base() << std::endl;
|
|
VectorArray[(**client).Type].erase( it );
|
|
}
|
|
}
|
|
|
|
std::cout << "DELTE CLIENT: "<< (**client).client.getIpAddress() << ":" << (**client).serverMemAddr << " (" << *client << ")..." << std::endl;
|
|
|
|
deleteAndSetToNull(client);
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
|
|
void * redirectThreadFunction( void * data ) {
|
|
|
|
auto tD = reinterpret_cast<redirectThreadData *>(data);
|
|
char buffer;
|
|
|
|
std::cout << " __-->Thread; Redirect " << (*tD->cli1)->Type << " to " << (*tD->cli2)->Type << std::endl;
|
|
|
|
while ( ! shouldStop ) {
|
|
|
|
if( read( (*tD->cli1)->client.getSocket(), &buffer, 1) <= 0 ) {
|
|
std::cerr << " DEBUG: read() failed: IN redirectThreadFunction() " << std::endl;
|
|
if(*tD->cli2 && *tD->cli2)
|
|
(*tD->cli2)->client.closeSocket();
|
|
else
|
|
std::cerr << "INFo: Konnte CLIENT 2 nicht Clossock'en, da der Pointer auf nullptr zeigte." << std::endl;
|
|
|
|
closeConnectionWithClient(tD->cli1, true);
|
|
break;
|
|
|
|
} else if ( write((*tD->cli2)->client.getSocket(), &buffer, 1) <= 0) {
|
|
std::cerr << " DEBUG: write() failed." << std::endl;
|
|
if(*tD->cli2 && *tD->cli2)
|
|
(*tD->cli2)->client.closeSocket();
|
|
else
|
|
std::cerr << "INFo: Konnte CLIENT 2 nicht Clossock'en, da der Pointer auf nullptr zeigte." << std::endl;
|
|
closeConnectionWithClient(tD->cli1, true);
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::cout << "DELTE RectirectThreadData: "<< tD << "... & exit" << std::endl;
|
|
deleteAndSetToNull(&tD);
|
|
pthread_exit_WithRemoveFromThreadList();
|
|
}
|
|
|
|
|
|
void * updateServerThreadFunktion(void * Server) {
|
|
auto server = reinterpret_cast<Client *>(Server); // Client(x1) <---x1(yz) <---yz(ia)
|
|
// NewThread COPY(<--x1(yz)): <---x1(vb)
|
|
std::string buffer; //NewThread COPY: <-----yz(lol) => *yz
|
|
char c;
|
|
|
|
while ( ! shouldStop ) {
|
|
|
|
if( ! server ) {
|
|
std::cerr << "Server* in updateServerThreadFunktion is nullptr" << std::endl;
|
|
closeConnectionWithClient(&server, true);
|
|
pthread_exit_WithRemoveFromThreadList();
|
|
} else
|
|
buffer.clear();
|
|
|
|
do {
|
|
if( read( (*server).client.getSocket(), &c, 1) <= 0) {
|
|
std::cerr << " DEBUG: -> rev failed in updateServerThreadFunktion()." << std::endl;
|
|
closeConnectionWithClient(&server, true);
|
|
pthread_exit_WithRemoveFromThreadList( );
|
|
} else
|
|
buffer.push_back(c);
|
|
} while ( c != '|' && buffer.size() < buffer.max_size() ); //sicherheitslücke, da sonst passieren, kann, dass buffer überfüllt wird
|
|
|
|
if(buffer.data() && buffer.size() > 0) {
|
|
buffer.pop_back();
|
|
buffer.push_back('\0');
|
|
|
|
if(buffer.find("=") == std::string::npos) {
|
|
std::cout << " INVALID MSG: '" << buffer.data() << "'" << std::endl;
|
|
continue;
|
|
}
|
|
} else
|
|
std::cout << "recived msg: '" << buffer << "'" << std::endl;
|
|
|
|
std::string what = buffer.substr(0, buffer.find("="));
|
|
std::string value = buffer.substr(buffer.find("=") + 1);
|
|
|
|
if (what == "CONNECTIONS_LEFT") {
|
|
(*server).ConnectionsLeft = atoi(value.c_str());
|
|
|
|
} else {
|
|
std::cout << "Got invalid msg -> in updateServerThreadFunktion." << std::endl;
|
|
closeConnectionWithClient(&server, true);
|
|
pthread_exit_WithRemoveFromThreadList();
|
|
}
|
|
}
|
|
|
|
pthread_exit_WithRemoveFromThreadList();
|
|
}
|
|
|
|
|
|
|
|
void * threadFunctionHandlWaitingQueuqVector( void *) {
|
|
|
|
while ( !shouldStop ) {
|
|
std::cout << "Waiting for clients in queque..." << std::endl;
|
|
while ( WaitingQuequeList.size() == 0 && ! shouldStop )
|
|
usleep(50000);
|
|
std::cout << "New client in queque handler..." << std::endl;
|
|
|
|
Client * client = WaitingQuequeList.front();
|
|
WaitingQuequeList.erase(WaitingQuequeList.begin());
|
|
|
|
if(client == nullptr) {
|
|
std::cerr << "------->Error: Client* in Waiting Queuq is NULL" << std::endl;
|
|
continue;
|
|
|
|
} else if( (*client).Type == Client::SERVER ) {
|
|
|
|
std::cout << "New client = new server -> look if id is already used..." << std::endl;
|
|
bool noServerFound = true;
|
|
for ( auto &FSClient : ServerList ) {
|
|
if(FSClient->serverID == (*client).serverID ) {
|
|
//error already server with this id hosted
|
|
std::cerr << "Error: es gibt bereits einen server mit dieser id: " << FSClient->serverID << std::endl;
|
|
closeConnectionWithClient(&client, false, "SERVERID_ALREADY_USED=true|");
|
|
noServerFound = false;
|
|
break;
|
|
}
|
|
} if( ! noServerFound )
|
|
continue;
|
|
//create update thread
|
|
|
|
pthread_t thread;
|
|
if(pthread_create(&thread, nullptr, updateServerThreadFunktion, reinterpret_cast<void*>( client )) != 0) {
|
|
perror("pthread create failed");
|
|
closeConnectionWithClient(&client, false, "SERVERID_ALREADY_USED=true|");
|
|
continue;
|
|
} else
|
|
threadList.push_back(thread);
|
|
std::cout << "Startet Update Thread at: ' " << thread << "'" << std::endl;
|
|
|
|
//Save data in vector
|
|
ServerList.push_back(client);
|
|
}
|
|
|
|
else if ( (*client).Type == Client::FROM_SERVER_CLIENT_FREE ) {
|
|
|
|
std::cout << "Check if server with Same IP && same mem addr exits: " << std::endl;
|
|
bool found_server = false;
|
|
for ( auto &serverInVec : ServerList )
|
|
if(serverInVec != nullptr && serverInVec->client.getIpAddress()==(*client).client.getIpAddress() && serverInVec->serverMemAddr==(*client).serverMemAddr && (found_server = true) ) {
|
|
std::cout << "Founded server: " << serverInVec->client.getIpAddress() <<"==" << (*client).client.getIpAddress()
|
|
<< " && " << serverInVec->serverMemAddr << "==" << (*client).serverMemAddr << std::endl;
|
|
break;
|
|
}
|
|
|
|
if(! found_server) {
|
|
std::cout << "No server with same ip & same mainClientMemAddr found" << std::endl;
|
|
closeConnectionWithClient(&client);
|
|
continue;
|
|
}
|
|
|
|
FromServerClientListFree.push_back(client);
|
|
}
|
|
|
|
else if ( (*client).Type == Client::FROM_USER_CLIENT ) {
|
|
|
|
//------------check server
|
|
std::cout << "Look for server with this id." << std::endl;
|
|
Client *server = nullptr;
|
|
for ( auto &serverInVec : ServerList )
|
|
if(serverInVec->serverID == (*client).serverID) {
|
|
server = serverInVec;
|
|
break;
|
|
}
|
|
|
|
if(server == nullptr) {
|
|
std::cout << "No server with this id found" << std::endl;
|
|
closeConnectionWithClient(&client, false, "NO_SERVER_WITH_THIS_ID_FOUND=true|");
|
|
continue;
|
|
}
|
|
std::cout << "server found.. Check if client limit is reached: Left: " << (*server).ConnectionsLeft << std::endl;
|
|
|
|
if((*server).ConnectionsLeft <= 0) {
|
|
std::cerr << "Error: clients Limit reached." << std::endl;
|
|
closeConnectionWithClient(&client, false, "CLIENT_LIMIT_REACHED=true|");
|
|
continue;
|
|
|
|
} else if( (*server).client.send_("NEW_CLIENT_NEEDED=true|", 23) <= 0) {
|
|
//send failed.. error
|
|
std::cout << "send Failed" << std::endl;
|
|
/// closeConnectionWithClient(server, true); nicht deleten because update Thread
|
|
closeConnectionWithClient(&client, false, "SEND_TO_SERVER_FAILED=true|");
|
|
continue;
|
|
}
|
|
|
|
//-------------check server client
|
|
|
|
std::cout << "Look for server client" << std::endl;
|
|
|
|
Client * serverClient = nullptr;
|
|
for ( unsigned i = 0; i < FromServerClientListFree.size(); i++ ) {
|
|
if(FromServerClientListFree.at(i)->serverID == (*client).serverID ) {
|
|
serverClient = FromServerClientListFree.at(i);
|
|
//remove serverclient from free list...
|
|
FromServerClientListFree.erase(FromServerClientListFree.begin() + i);
|
|
break;
|
|
}
|
|
}
|
|
if(serverClient == nullptr) {
|
|
std::cout << "No server with this id found" << std::endl;
|
|
closeConnectionWithClient(&client, false, "NO_SERVER_ClIENT_FOUND=true|");
|
|
continue;
|
|
}
|
|
std::cout << "server client found" << std::endl;
|
|
|
|
//do checks
|
|
std::cout << "check password" << std::endl;
|
|
if((*serverClient).serverPW != "" && (*serverClient).serverPW != (*client).serverPW ) {
|
|
std::cout << "Failed: wrong pw" << std::endl;
|
|
closeConnectionWithClient(&client, false, "WRONG_PASSWORD=true|");
|
|
closeConnectionWithClient(&serverClient);
|
|
continue;
|
|
}
|
|
std::cout << "password ok" << std::endl;
|
|
|
|
|
|
//send finished signal:
|
|
|
|
if((*client).client.send_("FINISHED=true|", 14) <= 0 ) {
|
|
std::cout << "send sinished signal failed" << std::endl;
|
|
closeConnectionWithClient(&client, false);
|
|
closeConnectionWithClient(&serverClient);
|
|
continue;
|
|
}
|
|
|
|
//Psuh back to vectors
|
|
FromUserClientListConnected.push_back(client);
|
|
FromServerClientListConnected.push_back(serverClient);
|
|
|
|
std::cout << "Start threads..." << std::endl;
|
|
//------------Start Threads:
|
|
bool error = false;
|
|
for (int i = 0; i < 2; ++i) {
|
|
redirectThreadData * newRedirectData = new redirectThreadData( &((i == 0) ? FromUserClientListConnected.back() : FromServerClientListConnected.back()),
|
|
&((i == 0) ? FromServerClientListConnected.back() : FromUserClientListConnected.back()) );
|
|
std::cout << "Creted new Redirect ThreadData: " << newRedirectData << " -> CLI_1: " << *newRedirectData->cli1
|
|
<< " -> CLI_2" << *newRedirectData->cli2 << std::endl;
|
|
|
|
|
|
pthread_t thread;
|
|
if(pthread_create(&thread, nullptr, redirectThreadFunction, reinterpret_cast<void*>( newRedirectData )) != 0 && (error = true) ) {
|
|
perror("pthread create failed");
|
|
closeConnectionWithClient(&client, true);
|
|
closeConnectionWithClient(&serverClient, true);
|
|
break;
|
|
} else
|
|
threadList.push_back(thread);
|
|
|
|
std::cout << "Startet Redirect Thread at: ' " << thread << "'" << std::endl;
|
|
|
|
} if(error)
|
|
continue;
|
|
|
|
} else {
|
|
std::cerr << "Error Client has invalid TYPE: '" << (*client).Type << std::endl;
|
|
closeConnectionWithClient(&client, false);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
pthread_exit_WithRemoveFromThreadList();
|
|
}
|
|
|
|
|
|
|
|
//#include <algorithm> /// tD->VectorArray[0].erase(std::remove(tD->VectorArray[0].begin(), tD->VectorArray[0].end(), tD), tD->VectorArray[0].end());
|
|
|
|
|
|
void *threadFunctionReciveInitData(void *threadData)
|
|
{
|
|
std::cerr << " + " << __FUNCTION__ << std::endl;
|
|
|
|
Client * client = reinterpret_cast<Client *>(threadData);
|
|
std::string buffer;
|
|
char c;
|
|
|
|
while ( ! shouldStop ) {
|
|
buffer.clear();
|
|
do {
|
|
if( read(client->client.getSocket(), &c, 1) <= 0) {
|
|
std::cerr << " DEBUG: -> rev failed in threadFunctionReciveInitData()." << std::endl;
|
|
pthread_exit_WithRemoveFromThreadList( &client );
|
|
} else
|
|
buffer.push_back(c);
|
|
} while ( c != '|' && buffer.size() < buffer.max_size() ); //sicherheitslücke, da sonst passieren, kann, dass buffer überfüllt wird
|
|
|
|
if(buffer.data() && buffer.size() > 0) {
|
|
buffer.pop_back();
|
|
buffer.push_back('\0');
|
|
|
|
if(buffer.find("=") == std::string::npos) {
|
|
std::cout << " INVALID MSG: '" << buffer.data() << "'" << std::endl;
|
|
continue;
|
|
}
|
|
}
|
|
std::cout << "recived msg: '" << buffer << "'" << std::endl;
|
|
|
|
std::string what = buffer.substr(0, buffer.find("="));
|
|
std::string value = buffer.substr(buffer.find("=") + 1);
|
|
|
|
if(what == "TYPE") {
|
|
if(strcmp( value.c_str(), "SERVER") == 0)
|
|
client->Type = Client::TYPE::SERVER;
|
|
else if (strcmp( value.c_str(), "FROM_SERVER_CONNECTION") == 0)
|
|
client->Type = Client::TYPE::FROM_SERVER_CLIENT_FREE;
|
|
else if (strcmp( value.c_str(), "FROM_USER_CONNECTION") == 0)
|
|
client->Type = Client::TYPE::FROM_USER_CLIENT;
|
|
else
|
|
client->Type = Client::TYPE::UNKNOWN;
|
|
} else if (what == "SERVERID")
|
|
client->serverID = value;
|
|
else if (what == "PASSWORD")
|
|
client->serverPW = value;
|
|
else if (what == "CONNECTIONS_LEFT")
|
|
client->ConnectionsLeft = atoi(value.c_str());
|
|
else if (what == "MEM_ADDR")
|
|
client->serverMemAddr = value;
|
|
/*else if (what == "-")
|
|
tD->;*/
|
|
else if (what == "FINIDHED") {
|
|
std::cout << "INIT FINISHED: " << client->Type << " - "
|
|
<< client->serverID << " - " << client->serverPW
|
|
<< " - " << client->ConnectionsLeft << " - " << client << std::endl;
|
|
|
|
WaitingQuequeList.push_back(client);
|
|
pthread_exit_WithRemoveFromThreadList();
|
|
|
|
} else {
|
|
std::cout << "Got invalid msg -> bad client -> error -> kick client" << std::endl;
|
|
pthread_exit_WithRemoveFromThreadList(&client); // with clossocket in destructor of client
|
|
}
|
|
}
|
|
|
|
pthread_exit_WithRemoveFromThreadList();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void * acceptThread( void *) {
|
|
std::cerr << " + " << __FUNCTION__ << std::endl;
|
|
|
|
while ( ! shouldStop ) {
|
|
Client *newThreadData = new Client();
|
|
|
|
if(server.acceptClient(newThreadData->client) != 0) {
|
|
std::cerr << " -> Accpted failed: " << server.getLastError() << std::endl;
|
|
deleteAndSetToNull( &newThreadData );
|
|
continue;
|
|
} else
|
|
std::cout << " -> Accepted client: " << newThreadData->client.getIpAddress() << std::endl;
|
|
|
|
threadList.push_back(0);
|
|
pthread_t * thread = &threadList.back();
|
|
|
|
if(pthread_create(thread, nullptr, threadFunctionReciveInitData, reinterpret_cast<void*>( newThreadData )) != 0) {
|
|
perror(" -> pthread_creater failed");
|
|
deleteAndSetToNull( &newThreadData ); // with clossocket
|
|
continue;
|
|
} else
|
|
std::cout << " -> Startet threadFunctionReciveInitData at: '" << thread << "'" << std::endl;
|
|
|
|
}
|
|
|
|
std::cerr << " - " << __FUNCTION__ << std::endl;
|
|
|
|
pthread_exit_WithRemoveFromThreadList();
|
|
}
|
|
|
|
|
|
//#include <signal.h> // für signal() function, weil send gibt SIGPIPE zurück, (wenn letzter prozess beendet oder so... nur für schellscripts nötig),
|
|
|
|
|
|
int main(/*int argc, char *argv[]*/)
|
|
{
|
|
signal(SIGSTOP, SIG_IGN);
|
|
|
|
|
|
std::cerr << " + " << __FUNCTION__ << std::endl;
|
|
|
|
while ( server.startListening(serverPort) ) {
|
|
std::cerr << "-> Start Server failed: " << server.getLastError() << std::endl;
|
|
sleep(1);
|
|
}
|
|
std::cout << "-> Startet Server. Listening on: " << serverPort << std::endl;
|
|
|
|
std::cout << "-> Starting queque handler..." << std::endl;
|
|
threadList.push_back(0);
|
|
if(pthread_create(&threadList.back(), nullptr, threadFunctionHandlWaitingQueuqVector, nullptr) != 0) {
|
|
perror("pthread_creater failed");
|
|
return -1;
|
|
}
|
|
std::cout << "-> Startet queque handler at: '" << &threadList.back() << "'" << std::endl;
|
|
|
|
|
|
threadList.push_back(0);
|
|
if(pthread_create(&threadList.back(), nullptr, acceptThread, nullptr) != 0) {
|
|
perror("Konnte StopThread nicht starten");
|
|
return -1;
|
|
}
|
|
std::cout << "Started Accpet Thread: '" << threadList.back() <<"' ." << std::endl;
|
|
|
|
|
|
|
|
|
|
while ( ! shouldStop ) {
|
|
|
|
std::string line;
|
|
std::getline(std::cin, line);
|
|
if( line =="" )
|
|
continue;
|
|
else if(line == "stop")
|
|
shouldStop = true;
|
|
else if (line == "list") {
|
|
for (unsigned i = 0; i < (sizeof(VectorArray) / sizeof (VectorArray[0])) ; ++i)
|
|
for (unsigned x = 0; x < VectorArray[i].size(); ++x)
|
|
std::cout << "TDArray[" << i << "][" << x << "] Type: " << VectorArray[i][x]->Type << " IP: " << VectorArray[i][x]->client.getIpAddress()
|
|
<< " ID: " << VectorArray[i][x]->serverID << " PW: " << VectorArray[i][x]->serverPW << " ConLeft: " << VectorArray[i][x]->ConnectionsLeft << std::endl;
|
|
}
|
|
else {
|
|
std::cout << "Gib 'stop' ein um den server zu stoppen\n Gibt 'list' ein um Alle (gelogten) Clients zu sehen." << std::endl;
|
|
}
|
|
|
|
}
|
|
|
|
//Stopping Server...
|
|
std::cout << "-> Stopping Server..." << std::endl;
|
|
|
|
|
|
std::cout << "Stoping Serverlistening..." << std::endl;
|
|
if(server.isListening() && server.stopListening() != 0)
|
|
std::cerr << "StopListing failed: " << server.getLastError() << std::endl;
|
|
|
|
|
|
for( auto &e : threadList ) {
|
|
if(pthread_cancel(e) != 0)
|
|
perror("pthreac_cancel failed");
|
|
if( pthread_join(e, nullptr) != 0)
|
|
perror("pthread_join failed");
|
|
else
|
|
std::cout << "Stopped: " << e << std::endl;
|
|
}
|
|
std::cout << "Clear ThreadList..." << std::endl;
|
|
threadList.clear();
|
|
|
|
for (unsigned i = 0; i < (sizeof(VectorArray) / sizeof (*VectorArray)); ++i) {
|
|
for (unsigned x = 0; x < VectorArray[i].size(); ++x) {
|
|
std::cout << "Delete: TDArray[" << i << "][" << x << "]..." << std::endl;
|
|
deleteAndSetToNull( &VectorArray[i][x] );
|
|
}
|
|
std::cout << "Clear TDArray[" << i << "]... " << std::endl;
|
|
VectorArray[i].clear();
|
|
}
|
|
|
|
|
|
std::cout << "Exit..." << std::endl;
|
|
|
|
std::cerr << " - " << __FUNCTION__ << std::endl;
|
|
return 0;
|
|
}
|