/*! * \brief Server::incomingConnection * \param socketDescriptor */ void Server::incomingConnection(qintptr socketDescriptor) { qDebug() << "Connecting to " << socketDescriptor; ConnectionHandler *handler = new ConnectionHandler(socketDescriptor, this); clientList.append(handler); connect(handler, SIGNAL(finished()), handler, SLOT(deleteLater())); handler->start(); }
bool TCPListener::Send(Message *m) { auto it = _conHndlrs.find(m->Conn()); if (it != _conHndlrs.end()) { Connection *c = it->first; ConnectionHandler *h = it->second; if (c->IsOpen()) { h->Send(m); } else { _conHndlrs.erase(it); delete h; if (m->Owner() == 0) delete m; } return true; } else if (m->Cmd() == "") // skip dummy messages { if (m->Owner() == 0) delete m; return true; } return false; }
void start() { std::cout << "Starting..." << "\n"; StreamSocket wsock(port); while (true) { ConnectionHandler* cHandler = cHandlerFactory->getNewHandler(); StreamSocket sock = wsock.accept(); std::cout << "Incoming connection!\n"; std::thread t([&](StreamSocket sock) {cHandler->handle(sock);}, sock); t.detach(); } }
void NetworkManager::incomingConnection(qintptr handle) { qDebug() << "Client connected"; QTcpSocket* socket = new QTcpSocket(); socket->setSocketDescriptor(handle); mConnections[handle] = socket; ConnectionHandler* connection = new ConnectionHandler(handle, socket); connect(connection, SIGNAL(networkReceivedData(int,unsigned char*,int)), this, SLOT(networkReceivedData(int,unsigned char*,int))); connect(connection, SIGNAL(clientDisconnected(int)), this, SLOT(clientDisconnect(int))); connection->start(); }
void waitAndGet(ConnectionHandler &connectionHandler) { while (true) { const short bufsize = 1024; char buf[bufsize]; cin.getline(buf, bufsize); string line(buf); if (!connectionHandler.sendLine(line) || shouldClose) { std::cout << "Disconnected. Exiting...\n" << std::endl; shouldClose = true; connectionHandler.close(); break; } } }
// Listen for incoming connections void Server::run() { // Timeout value struct timeval timeoutValue; timeoutValue.tv_sec = SOCKET_TIMEOUT; // Set for select() fd_set sockets; // Activity cout << "Listening for connections..." << endl; // Start listening for connections status = listen(listenSocket, 5); if (status == -1) cout << "listen error" << endl ; assert(status != -1); // Socket descriptor for incoming connection int newSocket; struct sockaddr_storage their_addr; socklen_t addr_size = sizeof(their_addr); while(!stopRequested) { // Clear the socket set and add the listen socket to the set FD_ZERO(&sockets); FD_SET(listenSocket, &sockets); select(listenSocket + 1, &sockets, NULL, NULL, &timeoutValue); if(FD_ISSET(listenSocket, &sockets)) { // Accept incoming connection and set timeout value (RCVTIMEO) newSocket = accept(listenSocket, (struct sockaddr *)&their_addr, &addr_size); status = setsockopt(newSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeoutValue, sizeof(struct timeval)); if (newSocket == -1) cout << "Accept returned " << errno << endl; else { ConnectionHandler* newConnection = new ConnectionHandler(newSocket); newConnection->start(); } } } // Close the socket descriptor and free the memory used by the host info list freeaddrinfo(host_info_list); close(listenSocket); }
/// Handle a signal from above /// For now we handle only terminate void handleSignal() { LOG_TRACE << "Signal received for connection to " << identifier(); m_connHandler->signalOccured( ConnectionHandler::TERMINATE ); nextOperation(); }
/// Connection base state machine void nextOperation() { NetworkOperation netOp = m_connHandler->nextOperation(); switch ( netOp.operation() ) { case NetworkOperation::READ: { LOG_TRACE << "Next operation: READ " << netOp.size() << " bytes from " << identifier(); if ( netOp.buffer() == NULL ) { LOG_FATAL << "Attempt to READ from " << identifier() << " to a NULL data block"; abort(); // here should be a system exception } if ( netOp.size() == 0 ) { LOG_FATAL << "Attempt to READ 0 bytes data block from " << identifier(); abort(); // here should be a system exception } if ( netOp.timeout() > 0 ) setTimeout( netOp.timeout()); m_readBuffer = netOp.buffer(); socket().async_read_some( boost::asio::buffer( m_readBuffer, netOp.size() ), m_strand.wrap( boost::bind( &ConnectionBase::handleRead, this->shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred ))); break; } case NetworkOperation::WRITE: { LOG_TRACE << "Next operation: WRITE " << netOp.size() << " bytes to " << identifier(); if ( netOp.data() == NULL ) { LOG_FATAL << "Attempt to WRITE a NULL data block to " << identifier(); abort(); // here should be a system exception } if ( netOp.size() == 0 ) { LOG_FATAL << "Attempt to WRITE a 0 bytes data block to " << identifier(); abort(); // here should be a system exception } if ( netOp.timeout() > 0 ) setTimeout( netOp.timeout()); boost::asio::async_write( socket(), boost::asio::buffer( netOp.data(), netOp.size() ), m_strand.wrap( boost::bind( &ConnectionBase::handleWrite, this->shared_from_this(), boost::asio::placeholders::error ))); break; } case NetworkOperation::CLOSE: { LOG_TRACE << "Next operation: CLOSE connection to " << identifier(); // Initiate graceful connection closure. setTimeout( 0 ); unregister(); m_strand.post( boost::bind( &ConnectionBase::handleShutdown, this->shared_from_this() )); break; } case NetworkOperation::NOOP: LOG_TRACE << "Next operation: NOOP on connection to " << identifier(); break; } }
/// Handle the completion of a timer operation. void handleTimeout( const boost::system::error_code& e ) { if ( !e ) { m_connHandler->signalOccured( ConnectionHandler::TIMEOUT ); LOG_DEBUG << "Timeout on connection to " << identifier(); nextOperation(); } else { assert( e == boost::asio::error::operation_aborted ); } }
void waitAndListen(ConnectionHandler &connectionHandler) { while (true) { string answer; int len; if (!connectionHandler.getLine(answer)) { std::cout << "Disconnected. Exiting...\n" << std::endl; break; } len=answer.length(); answer.resize(len-1); cout << answer << std::endl << std::endl; if (answer == "SYSMSG QUIT ACCEPTED" || shouldClose) { shouldClose = true; connectionHandler.close(); std::cout << "Exiting...\n" << std::endl; break; } } }
void *ListenInput() { while (running) { std::string answer; int len; if (!connectionHandler.getLine(answer)) { std::cout << "Disconnected. Exiting...\n" << std::endl; running = false; break; } len=answer.length(); // A C string must end with a 0 char delimiter. When we filled the answer buffer from the socket // we filled up to the \n char - we must make sure now that a 0 char is also present. So we truncate last character. answer.resize(len-1); std::cout << answer << " " << std::endl << std::endl; } connectionHandler.close(); return NULL; }
/// Handle completion of a read operation. void handleRead( const boost::system::error_code& e, std::size_t bytesTransferred ) { setTimeout( 0 ); if ( !e ) { LOG_TRACE << "Read " << bytesTransferred << " bytes from " << identifier(); m_connHandler->networkInput( m_readBuffer, bytesTransferred ); } else { LOG_TRACE << "Read error: " << e.message(); signalError( e ); } nextOperation(); }
//////////////////////////////////////////////////////////////////////////////// /// Registers a client connection handler with the server. /// /// @ErrorHandling Throws a std::runtime_error if either m_handler has already /// been initialized or the passed function is null. /// @pre m_handler must not be initialized. /// @post Assigns the passed function to m_handler. /// @param h The callback function to handle client connections. /// /// @limitations This function can only be called once. //////////////////////////////////////////////////////////////////////////////// void CTcpServer::RegisterHandler(ConnectionHandler h) { Logger.Trace << hdr() << __PRETTY_FUNCTION__ << std::endl; if( !m_handler.empty() ) { throw std::runtime_error(hdr() + "Cannot override client handler."); } if( h.empty() ) { throw std::runtime_error(hdr() + "Cannot use null client handler."); } m_handler = h; Logger.Notice << hdr() << "Set client connection handler." << std::endl; }
int main (int argc, char *argv[]) { if (argc < 3) { std::cerr << "Usage: " << argv[0] << " host port" << std::endl << std::endl; return -1; } std::string host = argv[1]; short port = atoi(argv[2]); if (!connectionHandler.connect(host, port)) { std::cerr << "Cannot connect to " << host << ":" << port << std::endl; return 1; } std::thread t1(SendOutput); std::thread t2(ListenInput); t1.join(); t2.join(); return 0; }
void *SendOutput() { while (running) { const short bufsize = 1024; char buf[bufsize]; std::cin.getline(buf, bufsize); std::string line(buf); if (!connectionHandler.sendLine(line)) { std::cout << "Disconnected. Exiting...\n" << std::endl; running = false; break; } if (line == "QUIT") { std::cout << "Exiting...\n" << std::endl; running = false; break; } } return NULL; }
/// Translate network error to processor error void signalError( const boost::system::error_code& e ) { ConnectionHandler::NetworkSignal ns; std::string name; int errorcode = e.value(); #if defined(_WIN32) #ifdef WITH_SSL // Rewrite error code got for a missing SSL_shutdown to a connection reset // because on Windows SSL_shutdown may not be called: if (e.category() == boost::asio::error::get_ssl_category() && e.value() == ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ)) { LOG_DEBUG << "Connection terminated abruptly by client, got no SSL_shutdown(); " << "error: " << e.value() << ", category: " << e.category().name() << ", message: " << e.message(); errorcode = boost::asio::error::connection_reset; } #endif #endif switch( errorcode ) { case boost::asio::error::eof : ns = ConnectionHandler::END_OF_FILE; name = "EOF"; break; case boost::asio::error::operation_aborted : ns = ConnectionHandler::OPERATION_CANCELLED; name = "OPERATION CANCELLED"; break; case boost::asio::error::broken_pipe : ns = ConnectionHandler::BROKEN_PIPE; name = "BROKEN PIPE"; break; case boost::asio::error::connection_reset : ns = ConnectionHandler::CONNECTION_RESET; name = "CONNECTION RESET"; break; default: { std::string err = e.message(); #ifdef WITH_SSL if ( e.category() == boost::asio::error::get_ssl_category() ) { err = std::string( "(" ) + boost::lexical_cast< std::string >( ERR_GET_LIB( e.value() ) ) + ", " + boost::lexical_cast< std::string >( ERR_GET_FUNC( e.value() ) )+ ", " + boost::lexical_cast< std::string >( ERR_GET_REASON( e.value() ) ) + ")"; //ERR_PACK /* crypto/err/err.h */ char buf[ 128 ]; ::ERR_error_string_n( e.value(), buf, sizeof( buf ) ); err += buf; } #endif // WITH_SSL LOG_DEBUG << "Unknown error: " << e.value() << ", category: " << e.category().name() << ", message: " << err; ns = ConnectionHandler::UNKNOWN_ERROR; name = "UNKNOWN ERROR"; break; } } m_connHandler->signalOccured( ns ); LOG_DATA << "Signalled " << name << " to processor for connection to " << identifier(); }