/** * prüft auf neue Clients. * * @author FloSoft */ bool LobbyServer::CheckForNewClients() { SocketSet set; set.Add(serverSock_); if( set.Select(0, 0) > 0) { if(set.InSet(serverSock_)) { Socket client = serverSock_.Accept(); if(!client.isValid()) return false; unsigned playerid = static_cast<unsigned>(players.size()); while(players.find(playerid) != players.end()) ++playerid; LOG.write("New client connected from %s\n") % client.GetPeerIP(); LobbyPlayer p; p.attach(client, playerid); players[playerid] = p; LOG.write("Player-ID %d\n") % playerid; p.Send(new LobbyMessage_Id(playerid), true); } } return true; }
void SocketServer::service() { // Add listeners SocketSet sockSet; for (unsigned i = 0; i < ports.size(); i++) sockSet.add(ports[i]->socket, SocketSet::READ); // Add others addConnectionSockets(sockSet); if (sockSet.select(0.1) || connectionsReady()) { // Process connections processConnections(sockSet); // Accept new connections for (unsigned i = 0; i < ports.size() && !shouldShutdown(); i++) { try { Socket &socket = ports[i]->socket; if (!sockSet.isSet(socket, SocketSet::READ)) continue; IPAddress clientIP; while (true) { SmartPointer<Socket> client = socket.accept(&clientIP); if (client.isNull()) break; // Check access if (!allow(clientIP.getIP())) { LOG_INFO(3, "Server access denied for " << clientIP); continue; } SocketConnectionPtr con = createConnection(client, clientIP); client = 0; // Release socket pointer if (con.isNull()) LOG_INFO(3, "Dropped server connection on " << ports[i]->ip << " from " << clientIP); else { connections.push_back(con); LOG_INFO(3, "Server connection id=" << con->getID() << " on " << ports[i]->ip << " from " << IPAddress(clientIP.getIP())); } } } CBANG_CATCH_ERROR; } }
/** * Hauptschleife. * * @author FloSoft */ void LobbyClient::Run(void) { if(state == CS_STOPPED) return; SocketSet set; // erstmal auf Daten überprüfen set.Clear(); // zum set hinzufügen set.Add(socket); if(set.Select(0, 0) > 0) { // nachricht empfangen if(!recv_queue.recv(socket)) { LOG.lprintf("Receiving Message from server failed\n"); ServerLost(); return; } } // nun auf Fehler prüfen set.Clear(); // zum set hinzufügen set.Add(socket); // auf fehler prüfen if(set.Select(0, 2) > 0) { if(set.InSet(socket)) { // Server ist weg LOG.lprintf("Error on socket to server\n"); ServerLost(); return; } } // maximal 10 Pakete verschicken if(!send_queue.send(socket, 10)) { ServerLost(); return; } // recv-queue abarbeiten while(recv_queue.count() > 0) { recv_queue.front()->run(this, 0xFFFFFFFF); recv_queue.pop(); } }
void Server::addConnectionSockets(SocketSet &sockSet) { SocketServer::addConnectionSockets(sockSet); for (iterator it = begin(); it != end(); it++) { Connection &con = *it->castPtr<Connection>(); switch (con.getState()) { case Connection::READING_HEADER: case Connection::READING_DATA: sockSet.add(con.getSocket(), SocketSet::READ); break; case Connection::WRITING_HEADER: case Connection::WRITING_DATA: if (!con.getContext() || con.getContext()->isReady()) sockSet.add(con.getSocket(), SocketSet::WRITE); break; default: break; } } }
int main() { Socket server(SockType::TCP); server.SetReuseAddr(true); server.SetBlocking(false); server.Bind(IpAddress("127.0.0.1:8999")); server.Listen(100); SocketSet Rs; Rs.Add(&server); SocketSet Ws; while (true) { int nRet = SocketSet::Select(Rs, Ws, 1000); if (nRet > 0) { for (auto R : Rs) { IpAddress Ip(nullptr); if (R == &server) { Socket* C = R->Accept(Ip); if (C) { Rs.Add(C); } } else { char Buffer[1024] = { 0 }; int Recv = R->Receive(Buffer, 1024); if (Recv>0) printf("kkkkk: R %s\n", Buffer); } } } } }
void Server::processConnections(SocketSet &sockSet) { if (!initialized) THROW("HTTP::Server not initialized"); // Save current thread ID and restore it before leaving this scope struct SmartThreadID { unsigned threadID; SmartThreadID() : threadID(Logger::instance().getThreadID()) {} ~SmartThreadID() {Logger::instance().setThreadID(threadID);} } smartThreadID; for (iterator it = begin(); it != end() && !shouldShutdown(); it++) { // Set thread ID = connection ID Logger::instance().setThreadID((*it)->getID()); processConnection(*it, sockSet.isSet((*it)->getSocket())); } }
/** * * * @author FloSoft */ Message* Message::recv(Socket& sock, int& error, bool wait, Message * (*createfunction)(unsigned short)) { error = -1; unser_time_t time = TIME.CurrentTick(); unser_time_t timeout = time; unsigned int received; SocketSet set; while(true) { // Warten wir schon 5s auf Antwort? if(time - timeout > 15000) wait = false; time = TIME.CurrentTick(); // SocketSet "saubermachen" set.Clear(); // Socket hinzufgen set.Add(sock); // liegen Daten an? int retval = set.Select(0, 0); if(retval <= 0) { if(wait) continue; if(retval != -1) error = 0; return NULL; } // liegen diese Daten an unserem Socket, bzw wieviele Bytes liegen an? if(!set.InSet(sock) || sock.BytesWaiting(&received) != 0) { if(wait) continue; error = 1; return NULL; } // socket ist geschlossen worden if(received == 0) return NULL; // haben wir schon eine vollständige nachricht? (kleinste nachricht: 6 bytes) if(received < 6) { if(wait) continue; error = 2; return NULL; } break; } int read = -1; char block[6]; unsigned short* id = (unsigned short*)&block[0]; unsigned int* length = (unsigned int*)&block[2]; // block empfangen read = sock.Recv(block, 6, false); if(read != 6) { LOG.write("recv: block: only got %d bytes instead of %d, waiting for next try\n", read, 6); if(read != -1) error = 3; return NULL; } read = sock.BytesWaiting(); static unsigned int blocktimeout = 0; if(read < (signed)((*length) + 6) ) { ++blocktimeout; LOG.write("recv: block-waiting: not enough input (%d/%d) for message (0x%04X), waiting for next try\n", read, (*length) + 6, *id); if(blocktimeout < 120 && read != -1) error = 4; return NULL; } blocktimeout = 0; // Block nochmals abrufen (um ihn aus dem Cache zu entfernen) read = sock.Recv(block, 6); if(read != 6) { LOG.lprintf("recv: id,length: only got %d bytes instead of %d\n", read, 2); return NULL; } Message* msg = createfunction(*id); if(!msg) return NULL; // Daten abrufen msg->recv(sock, *length); return msg; }
/** * verarbeitet alle Nachrichten der Clients. * * @author FloSoft */ bool LobbyServer::ProcessMessages() { SocketSet set; // In einem SocketSet alle Clients hinzufügen und gucken, ob etwas empfangen wurde for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it) { LobbyPlayer& p = it->second; if(!p.isFree()) p.addToSet(set); } if(set.Select(0, 0) > 0) { for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it) { LobbyPlayer& p = it->second; if(p.inSet(set) && !p.Receive()) Disconnect(p); } } set.Clear(); // In einem SocketSet alle Clients hinzufügen und gucken, ob fehler aufgetreten sind for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it) { LobbyPlayer& p = it->second; if(!p.isFree()) p.addToSet(set); } if(set.Select(0, 2) > 0) { LOG.write("Error on Sockets\n"); for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it) { LobbyPlayer& p = it->second; if( p.inSet(set) ) { LOG.write("Player %d: Connection lost\n") % p.getId(); Disconnect(p); } } } // Nachrichten-Queues der Spieler abschicken (max 10 Nachrichten pro Spieler pro Runde) for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it) { LobbyPlayer& p = it->second; if(!p.Send()) Disconnect(p); else p.Run(this); } return true; }
void Waitable::wait(int timeout) { SocketSet set; set.add(this); set.wait(timeout); }
int main(int argc, char ** argv) { string data; stringstream buf; unsigned int i; Stats stats; ClientSet clients; SocketSet sockets; Switchboard switchboard; ArgumentSet arguments(argc, argv); if (arguments.isset("version") || arguments.isset("v")) { cout << PACKAGE_NAME << " version " << PACKAGE_VERSION << endl; return 0; } if (arguments.isset("help") || arguments.isset("h")) { cout << endl; cout << "usage: istatd [-a HOST] [-p PORT]" << endl; cout << endl; cout << " -d run in background" << endl; cout << " -h print this help text" << endl; cout << " -v print version number" << endl; cout << endl; cout << " -c FILE custom config file location" << endl; cout << " -a HOST listen on this address" << endl; cout << " -p PORT listen on this port" << endl; cout << " -u USER change running user" << endl; cout << " -g GROUP change running group" << endl; cout << endl; cout << " --pid=FILE custom pid file location" << endl; cout << " --cache=DIR custom cache file location" << endl; cout << " --socket=FILE custom socket file location" << endl; cout << " --code=CODE custom lock code" << endl; cout << endl; return 0; } // Load and parse configuration Config config(arguments.get("c", CONFIG_FILE_PATH)); config.parse(); config.validate(); // Load configuration properties from command line and config file bool arg_d = arguments.isset("d"); string cf_network_addr = arguments.get("a", config.get("network_addr", "0.0.0.0")); string cf_network_port = arguments.get("p", config.get("network_port", "5109")); string cf_server_user = arguments.get("u", config.get("server_user", "istat")); string cf_server_group = arguments.get("g", config.get("server_group", "istat")); string cf_server_pid = arguments.get("pid", config.get("server_pid", "")); string cf_cache_dir = arguments.get("cache", config.get("cache_dir", "/var/cache/istat")); string cf_server_socket = arguments.get("socket", config.get("server_socket", "/tmp/istatd.sock")); #ifdef HAVE_LIBKSTAT if(-1 == kstat_init()) return 1; #endif Daemon unixdaemon(cf_server_pid, cf_server_socket, cf_cache_dir); Socket listener(cf_network_addr, to_int(cf_network_port)); SignalResponder signalresponder(&sockets, &listener, &unixdaemon, &clients); ::pn_signalresponder = &signalresponder; // Create socket, pid file and put in background if desired unixdaemon.create(arg_d, cf_server_user, cf_server_group); // Get old sessions from disk cache clients.read_cache(cf_cache_dir); // Clear cache of saved sessions if (arguments.isset("clear-sessions")) { clients.clear_cache(); return 0; } signal(SIGHUP, handler); signal(SIGUSR1, handler); signal(SIGINT, handler); signal(SIGTERM, handler); signal(SIGPIPE, handler); if (!listener.listen()) return 1; sockets += listener; // Add disks for monitoring if (config.get("monitor_disk") != "") { // No array found. Add value given. stats.add_disk(config.get("monitor_disk").c_str()); } else { // Array found. Add all values in the array. for (i = 0; i < config.get_property("monitor_disk").get_array_size(); i++) { stats.add_disk(config.get_property("monitor_disk").get_array(i).c_str()); } } // Add network interfaces for monitoring if (config.get("monitor_net") != "") { // No array found. Add value given. stats.add_net(config.get("monitor_net").c_str()); } else { // Array found. Add all values in the array. for (i = 0; i < config.get_property("monitor_net").get_array_size(); i++) { stats.add_net(config.get_property("monitor_net").get_array(i).c_str()); } } #ifdef HAVE_LIBSENSORS unsigned int sensor_num; struct sensor_data sensor_data; sensor_num = get_sensor_num(); for (i = 0; i < sensor_num; i++) { get_sensor_data(i, &sensor_data); stats.add_sensor(&sensor_data); } #endif #ifdef HAVE_QNAPTEMP struct sensor_data sensor_data; if (have_qnaptemp()) { get_qnaptemp(0, &sensor_data); stats.add_sensor(&sensor_data); } #endif while (1) { stats.update_system_stats(); if (sockets.get_status(1)) { if (sockets == listener) { Socket new_socket(listener.accept()); sockets += new_socket; } else { Socket active_socket(sockets.get_ready()); if (active_socket.receive(data, 1024)) { switchboard.parse(&sockets, &clients, &config, &active_socket, &stats, &arguments, data); } else { sockets -= active_socket; } } } } ::pn_signalresponder = NULL; return 0; }