void KeyValueStore::InternalThread::incomingRoutine() { const Config::ServerInformation& info = config.getServerInformation(); Config::ThreadControl& control = config.getThreadControl(); Mutex& inMutex = control.getInMutex(); Condition& cond = control.getInCondition(); Thread incoming; Incoming inTask; int currId = -1; static bool first = true; // Init connection info SocketAddress sock(info.address, info.internalPort); ServerSocket server; try { server.bind(sock, true); server.listen(5); } catch(Exception& e) { printKv("Could not initialize internal thread, please restart server ("<< e.displayText()<< ")"); } StreamSocket client; while(control.isLive()) { inMutex.lock(); cond.wait(inMutex); unsigned nextId = control.getConnectedId(); inMutex.unlock(); // NOTE: From a security perspective this is not safe. // if someone tries to connect at the same time a rejoin // was initiated, they could easily perform a MITM attack. // However, since this is an academic exercise, I am not too // concerned with security (as can be seen by many other components // in this system as well). if(currId != (int)nextId) { currId = nextId; // TODO: Update processing thread somehow printKv("Told a new server should be connecting..."); try { client = server.acceptConnection(); printKv("Incoming server connected: "<< currId); inTask.cancel(); if(!first) incoming.join(); first = false; inTask = Incoming(client, &config.getThreadControl()); incoming.start(inTask); printKv("Handling new server"); } catch(TimeoutException& e) { printKv("Server did not connect in time - we don't want the system to be hung up, though ("<< e.displayText() <<")"); } } } server.close(); }
virtual void run(){ try{ unsigned char buf[1000]; ServerSocket server; server.bind( "127.0.0.1", SocketFactoryTest::DEFAULT_PORT ); net::Socket* socket = server.accept(); server.close(); socket->setSoLinger( false, 0 ); synchronized(&mutex) { numClients++; mutex.notifyAll(); } while( !done && socket != NULL ){ io::InputStream* stream = socket->getInputStream(); memset( buf, 0, 1000 ); try{ if( stream->read( buf, 1000, 0, 1000 ) == -1 ) { done = true; continue; } lastMessage = (char*)buf; if( strcmp( (char*)buf, "reply" ) == 0 ){ io::OutputStream* output = socket->getOutputStream(); output->write( (unsigned char*)"hello", (int)strlen("hello"), 0, (int)strlen("hello") ); } }catch( io::IOException& ex ){ done = true; } } socket->close(); delete socket; numClients--; synchronized(&mutex) { mutex.notifyAll(); } }catch( io::IOException& ex ){ printf("%s\n", ex.getMessage().c_str() ); CPPUNIT_ASSERT( false ); }catch( ... ){ CPPUNIT_ASSERT( false ); } }
int main(int argc, const char * argv[]) { ServerSocket mainSocket = ServerSocket(4444); Socket socket = mainSocket.acceptConnection(); socket.beginHandling(); socket.closeSocket(); mainSocket.close(); return 0; }
/** Public thread methods (clients connect here) */ void KeyValueStore::PublicThread::run() { Thread threads[MAX_CLIENT_THREADS]; HandleClient threadInst[MAX_CLIENT_THREADS]; const Config::ServerInformation& info = config.getServerInformation(); Config::ThreadControl& control = config.getThreadControl(); int id = 0; char full = Protocol::SRV_FULL; char conn = Protocol::SRV_CONN; ServerSocket server; SocketAddress sock(info.address, info.pubPort); server.bind(sock, true); server.listen(5); printKv("Listening for clients on "<< info.address <<":"<< info.pubPort); while(control.isLive()) { // Simply do thread per client StreamSocket client = server.acceptConnection(); printKv("Received client connection request - waiting for thread to free up"); // Wait five seconds try { freeThreads.wait(5000); // This beats busy waiting } catch(TimeoutException& notUsed(e)) { printKv("Server full - closing connection to client"); client.sendBytes(&full, sizeof(full)); client.close(); continue; } // Send success client.sendBytes(&conn, sizeof(conn)); // tryJoin() doesn't work properly in linux, using isRunning() instead // actively search for the next available thread while(threads[id].isRunning()){ // Try to get an available thread id = (id + 1) % MAX_CLIENT_THREADS; Thread::sleep(250); // 250ms between each check } printKv("Serving client"); threadInst[id] = HandleClient(client, control); threads[id].start(threadInst[id]); } server.close(); freeThreads.set(); // Free a thread with semaphore }
void SocketTest::testConnectRefused() { ServerSocket serv; serv.bind(SocketAddress()); serv.listen(); Poco::UInt16 port = serv.address().port(); serv.close(); StreamSocket ss; Timespan timeout(250000); try { ss.connect(SocketAddress("localhost", port)); fail("connection refused - must throw"); } catch (ConnectionRefusedException&) { } }
void LocalSocketTest::testConnectRefusedNB() { SocketAddress sas("/tmp/poco.server.tcp.sock"); ServerSocket serv; serv.bind(sas); serv.listen(); serv.close(); StreamSocket ss; Timespan timeout(10000); SocketAddress sac("/tmp/poco.client.tcp.sock"); try { ss.connect(sas, timeout, &sac); fail("connection refused - must throw"); } catch (TimeoutException&) { } catch (ConnectionRefusedException&) { } }
int #ifdef WIN32_SERVICE hermes_main #else main #endif //WIN32_SERVICE (int argc,char *argv[]) { /* TODO:think of this again if(argc>2) { for(unsigned i=1;i<argc;i++) { argv++ } */ #ifdef HAVE_SSL CRYPTO_set_locking_callback(ssl_locking_function); #ifndef WIN32 //getpid() returns different values for threads on windows, therefor this is not needed CRYPTO_set_id_callback(pthread_self); #endif //WIN32 #endif //HAVE_SSL try { if(2==argc) { if(!Utils::file_exists(argv[1])) throw Exception(string(_("Config file "))+argv[1]+_(" doesn't exist or is not readable."),__FILE__,__LINE__); cfg.parse(argv[1]); } else throw Exception(_("Config file not specified"), __FILE__, __LINE__); cfg.validateConfig(); } catch(Exception &e) { LERR(e); return -1; } unsigned long nconns=0; signal(SIGTERM,exit_requested); signal(SIGINT,exit_requested); #ifndef WIN32 signal(SIGCHLD,SIG_IGN); signal(SIGPIPE,SIG_IGN); #endif //WIN32 //we have to create the server socket BEFORE chrooting, because if we don't, //SSL cannot initialize because it's missing libz ServerSocket server; pthread_t cleaner_thread; string peer_address; #ifndef WIN32 if(cfg.getBackground()) { int retval; retval=fork(); if(retval>0) exit(0); //succesful fork if(retval<0) { LERR(_("Error forking into the background") + Utils::errnotostrerror(errno)); return -1; } } if(cfg.getPidFile()!="") { try { Utils::write_pid(cfg.getPidFile(),getpid()); } catch(Exception &e) { LERR(e); } } if(cfg.getChroot()!="") { //this is needed to get hermes to load the dns resolver BEFORE chrooting (void)gethostbyname("hermes-project.com"); if(-1 == chdir(cfg.getChroot().c_str())) { LERR(_("Couldn't chdir into ") + cfg.getChroot() + " " + Utils::errnotostrerror(errno) ); return -1; } if(-1==chroot(cfg.getChroot().c_str())) { LERR(_("Couldn't chroot ") + Utils::errnotostrerror(errno)); return -1; } if(-1 == chdir("/")) { LERR(_("Couldn't chdir into /, this shouldn't happen: " + Utils::errnotostrerror(errno)) ); return -1; } } #endif //WIN32 LINF("Starting hermes with pid "+Utils::inttostr(getpid())); try { server.init(); server.setPort(cfg.getListeningPort()); server.listen(cfg.getListeningPort(),cfg.getBindTo()); } catch(Exception &e) { LERR(e); return -1; //couldn't bind, exit } #ifndef WIN32 if(cfg.getDropPrivileges()) { //drop privileges once we have opened the listening port if(-1 == setgroups(0,NULL)) { LERR(_("Error dropping priviledges " + Utils::errnotostrerror(errno)) ); return -1; } if(-1 == setgid(cfg.getGid())) { LERR(_("Error setting gid " + Utils::inttostr(cfg.getGid()) + " " + Utils::errnotostrerror(errno)) ); return -1; } if(-1 == setuid(cfg.getUid())) { LERR(_("Error setting uid " + Utils::inttostr(cfg.getUid()) + " " + Utils::errnotostrerror(errno)) ); return -1; } if(-1 == setuid(cfg.getUid())) { LERR(_("Error setting uid " + Utils::inttostr(cfg.getUid()) + " " + Utils::errnotostrerror(errno)) ); return -1; } } #endif //WIN32 /* start our cleaner thread */ if(cfg.getCleanDb()) pthread_create(&cleaner_thread,NULL,cleaner_thread_run,NULL); new_conn_info info; stack<new_conn_info> info_stack; while(!quit) { if(server.canRead(1)) //wait one second for incoming connections, if none then loop again(allows us to check for SIGTERM and SIGINT) { pthread_t thread; pthread_attr_t thread_attr; pthread_attr_init(&thread_attr); pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); int retval; int fd=server.accept(&peer_address); info.new_fd=fd; info.peer_address=peer_address; info.connection_id=++nconns; pthread_mutex_lock(&info_stack_mutex); info_stack.push(info); pthread_mutex_unlock(&info_stack_mutex); retval=pthread_create(&thread,&thread_attr,thread_main,(void *)&info_stack); if(retval) { LERR(_("Error creating thread: ") + Utils::errnotostrerror(retval) + _(". Sleeping 5 seconds before continuing...")); sleep(5); } else { #ifdef WIN32 LDEB("New thread created [" + Utils::ulongtostr(nconns) + "] thread_id: " + Utils::ulongtostr((unsigned long)thread.p) + ":" + Utils::ulongtostr(thread.x)); #else LDEB("New thread created [" + Utils::ulongtostr(nconns) + "] thread_id: " + Utils::ulongtostr(thread)); #endif //WIN32 pthread_mutex_lock(&childrenlist_mutex); children.push_back(nconns); pthread_mutex_unlock(&childrenlist_mutex); } } } //close connection so that the port is no longer usable server.close(); // wait for all threads to finish LINF("Waiting for threads to finish"); #ifndef WIN32 while(children.size()) { if(false==cfg.getBackground()) { cout << "Threads active:" << children.size() << (char)13; fflush(stdout); } sleep(1); } #endif //WIN32 if(cfg.getCleanDb()) pthread_join(cleaner_thread,NULL); #ifndef WIN32 if(false==cfg.getBackground()) cout << endl; #endif //WIN32 #ifdef HAVE_SPF Spf::deinitialize(); #endif //HAVE_SPF return 0; }