/// /// Run when new connection is accepted /// /// @param memory_pool_ptr shared pointer to the allocated memory poll for connections /// @param i_connect index of current connection in memory pool /// @param e reference to error object /// void T_server::handle_accept( T_memory_pool_ptr memory_pool_ptr, size_t i_connect, const boost::system::error_code& e) { try { if (!e) { std::cout << "handle_accept() \n"; // get pointer of current connection T_connection * const current_memory_pool_raw_ptr = reinterpret_cast<T_connection *>( memory_pool_ptr.get() ); T_connection * const current_connection_raw_ptr = &(current_memory_pool_raw_ptr[i_connect]); T_connection::T_shared_this current_connection_ptr(memory_pool_ptr, current_connection_raw_ptr ); // schedule new task to thread pool current_connection_raw_ptr->run(boost::move(current_connection_ptr)); // sync launch of short-task: run() // increment index of connections ++i_connect; // if the limit of connections in the memory pool have been reached, then create a new memory pool if(i_connect == connections_in_memory_pool) { i_connect = 0; memory_pool_ptr.reset(new T_memory_pool, T_memory_pool_deleter() ); } // create next connection, that will accepted T_connection * const new_memory_pool_raw_ptr = reinterpret_cast<T_connection *>( memory_pool_ptr.get() ); T_connection * const new_connection_raw_ptr = T_connection::create(file_name_, new_memory_pool_raw_ptr, i_connect, io_service_executors_, timeout_); // start new accept operation acceptor_.async_accept(new_connection_raw_ptr->socket(), new_connection_raw_ptr->client_bind( boost::bind(&T_server::handle_accept, this, boost::move(memory_pool_ptr), // doesn't copy and doesn't use the atomic counter with memory barrier i_connect, ba::placeholders::error)) ); } } catch(const seh::T_seh_exception& e) { std::cerr << "T_seh_exception: " << e.what() << "\n ->throw place: " << THROW_PLACE << std::endl; } catch(const bs::system_error& e) { std::cerr << "Boost system_error exception: " << e.what() << "\n ->throw place: " << THROW_PLACE << std::endl; } catch(const std::exception &e) { std::cerr << "Exception: " << e.what() << "\n ->throw place: " << THROW_PLACE << std::endl; } catch(...) { std::cerr << "Unknown exception!" << "\n ->throw place: " << THROW_PLACE << std::endl; } }
void Connection::handle_read(const boost::system::error_code& e, size_t bytes_transferred, boost::tuple<ErrorHandler,Handler> handler, boost::shared_ptr<Connection> conn) { try { if (e) { boost::get<0>(handler)(e); } else { int originalSize = inbound_data_.size(); inbound_data_.resize(originalSize + bytes_transferred); int buffSize = originalSize + bytes_transferred; std::cout << originalSize << "+" << bytes_transferred << "=" << buffSize << std::endl; std::memcpy(&inbound_data_[originalSize],&inbound_buffer_[0],bytes_transferred); while(buffSize>=HEADER_SIZE) { // this means we have at least a header in our buffer int sz = inbound_data_[3]; sz = (sz << 8) | inbound_data_[2]; sz = (sz << 8) | inbound_data_[1]; sz = (sz << 8) | inbound_data_[0]; if(buffSize>=HEADER_SIZE+sz) { // we have a full message to parse! std::string archive_data(&inbound_data_[HEADER_SIZE], sz); Json::Value value; std::cout << archive_data << std::endl; if(reader.parse(archive_data,value)) { boost::get<1>(handler)(value); } if(HEADER_SIZE+sz<buffSize) { std::copy(&inbound_data_[HEADER_SIZE+sz],&inbound_data_[buffSize],&inbound_data_[0]); buffSize-=HEADER_SIZE+sz; } else { inbound_data_.clear(); buffSize = 0; } inbound_buffer_.resize(4); } else { inbound_buffer_.resize(sz); } } std::cout << "async read again: " << inbound_buffer_.size() << std::endl; boost::asio::async_read(socket_, boost::asio::buffer(inbound_buffer_), boost::bind(&Connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, handler,conn)); } } catch(std::exception& e) { std::cout << "Connection::handle_read_header: " << e.what() << std::endl; } }
void Server::accept_handler(socket_ptr _sock, const boost::system::error_code& e) { if ( !e ) { try { boost::thread(boost::bind( &Server::connection, this, _sock)); //thread( &Server::connection, this, _sock); } catch(exception& e) { CLOG_ERROR << "Exception: " << e.what() << endl; } } async_accept(); }
void RpcSessionNetHandler::sessionReadError( JMEngine::net::TcpSession::TcpSessionPtr session, boost::system::error_code e ) { try { session->stop(); LOGW("Rpc client from [ %s:%s ] disconnected", session->getIp(), session->getPort()); } catch(boost::system::system_error e) { LOGE("error ==> [ %d:%s ]", e.code().value(), e.what()); } }
void PeerManager::callback(const boost::system::error_code &e) { try { uint32_t minPeers = std::stoi(m_ctx.getDatabase()->getConfigValue("min_peers")); uint32_t numPeers = m_ctx.getOutMsgDisp().getTransport()->numPeers(); I2P_LOG(m_log, debug) << "current number of peers: " << numPeers; I2P_LOG(m_log, debug) << boost::log::add_value("peers", (uint32_t) numPeers); int32_t gap = minPeers - numPeers; for(int32_t i = 0; i < gap; i++) m_ctx.getOutMsgDisp().getTransport()->connect(m_ctx.getProfileManager().getPeer()); } catch(std::exception &e) { I2P_LOG(m_log, error) << "exception in PeerManager: " << e.what(); } if ( ! m_graceful ) { m_timer.expires_at(m_timer.expires_at() + boost::posix_time::time_duration(0, 0, 10)); m_timer.async_wait(boost::bind(&PeerManager::callback, this, boost::asio::placeholders::error)); } }
//////////////////////////////////////////////////////////////////////////////// /// This is the main communication engine. /// /// @IO /// At every timestep, a message is sent to the FPGA via TCP socket /// connection, then a message is retrieved from FPGA via the same /// connection. On the FPGA side, it's the reverse order -- receive and /// then send. Both DGI and FPGA receive functions will block until a /// message arrives, creating a synchronous, lock-step communication between /// DGI and the FPGA. We keep the timestep (a static member of CRtdsAdapter) /// very small so that how frequently send and receive get executed is /// dependent on how fast the FPGA runs. /// /// @Error_Handling /// Throws std::runtime_error if reading from or writing to socket fails. /// /// @pre Connection with FPGA is established. /// /// @post All values in the receive buffer are sent to the FPGA. All values in /// the send buffer are updated with data from the FPGA. /// /// @limitations This function uses synchronous communication. //////////////////////////////////////////////////////////////////////////////// void CRtdsAdapter::Run(const boost::system::error_code & e) { Logger.Trace << __PRETTY_FUNCTION__ << std::endl; if( e ) { if (e == boost::asio::error::operation_aborted) { return; } else { Logger.Fatal << "Run called with error: " << e.message() << std::endl; throw boost::system::system_error(e); } } // Always send data to FPGA first if( !m_txBuffer.empty() ) { boost::unique_lock<boost::shared_mutex> writeLock(m_txMutex); Logger.Debug << "Obtained the txBuffer mutex." << std::endl; EndianSwapIfNeeded(m_txBuffer); try { Logger.Debug << "Blocking for a socket write call." << std::endl; TimedWrite(m_socket, boost::asio::buffer(m_txBuffer, m_txBuffer.size() * sizeof(SignalValue)), CTimings::Get("DEV_SOCKET_TIMEOUT")); } catch(boost::system::system_error & e) { Logger.Fatal << "Send to FPGA failed: " << e.what(); throw; } EndianSwapIfNeeded(m_txBuffer); Logger.Debug << "Releasing the txBuffer mutex." << std::endl; } // Receive data from FPGA next if( !m_rxBuffer.empty() ) { // must be a unique_lock for endian swaps boost::unique_lock<boost::shared_mutex> writeLock(m_rxMutex); Logger.Debug << "Obtained the rxBuffer mutex." << std::endl; try { Logger.Debug << "Blocking for a socket read call." << std::endl; TimedRead(m_socket, boost::asio::buffer(m_rxBuffer, m_rxBuffer.size() * sizeof(SignalValue)), CTimings::Get("DEV_SOCKET_TIMEOUT")); } catch (boost::system::system_error & e) { Logger.Fatal << "Receive from FPGA failed: " << e.what(); throw; } EndianSwapIfNeeded(m_rxBuffer); if( m_buffer_initialized == false ) { m_buffer_initialized = true; for( unsigned int i = 0; i < m_rxBuffer.size(); i++ ) { if( m_rxBuffer[i] == NULL_COMMAND ) { m_buffer_initialized = false; } } if( m_buffer_initialized ) { Logger.Status << "Clientdata : " <<m_rxBuffer[0]<< std::endl; RevealDevices(); } } Logger.Debug << "Releasing the rxBuffer mutex." << std::endl; } // Start the timer; on timeout, this function is called again m_runTimer.expires_from_now( boost::posix_time::milliseconds(CTimings::Get("DEV_RTDS_DELAY"))); m_runTimer.async_wait(boost::bind(&CRtdsAdapter::Run, shared_from_this(), boost::asio::placeholders::error)); }
void handler(const boost::system::error_code& e, std::size_t size) { sensor_msgs::Imu imu; tf::Quaternion q; //using namespace serialization; namespace mt = ros::message_traits; if (!e) { std::istream is(&b); std::string line; std::getline(is, line); // cout <<"read:"<<size<<"###"<< line << endl; std::list<std::string> stringList; std::vector<std::string> list2; //boost::iter_split(stringList, line, boost::first_finder(",")); try { boost::iter_split(list2, line, boost::first_finder(",")); } catch (...) { cout << "bad" << endl; return; } if (list2.size() >= 6) { try { cout << "x:" << list2.at(4) << "\ty:" << list2.at(5) << "\tz:" << list2.at(6) << endl; cout << "gx:" << list2.at(8) << "\tgy:" << list2.at(9) << "\tgz:" << list2.at(10) << endl; /* auto q= tf::createQuaternionFromRPY(boost::lexical_cast<double>(list2.at(8)), boost::lexical_cast<double>(list2.at(9)), boost::lexical_cast<double>(list2.at(10))); */ imu.orientation = tf::createQuaternionMsgFromRollPitchYaw(boost::lexical_cast<double>(list2.at(8)), boost::lexical_cast<double>(list2.at(9)), boost::lexical_cast<double>(list2.at(10))); /* imu.orientation.x = q.x(); imu.orientation.y = q.y(); imu.orientation.z = q.z(); imu.orientation.w = q.w();*/ imu.linear_acceleration.x = boost::lexical_cast<double>(list2.at(4)); imu.linear_acceleration.y = boost::lexical_cast<double>(list2.at(5)); imu.linear_acceleration.z = boost::lexical_cast<double>(list2.at(6)); //ROS_ASSERT_MSG(impl_->md5sum_ == "*" || std::string(mt::md5sum<M>(*message)) == "*" || impl_->md5sum_ == mt::md5sum<M>(*message), // printf("Trying to publish message of type [%s/%s] on a publisher with type [%s/%s]", // mt::datatype<sensor_msgs::Imu>(*imu), mt::md5sum<sensor_msgs::Imu>(*message), // imu.datatype_.c_str(), impl_->md5sum_.c_str()); // imu_pub.publish(imu); } catch (exception &e) { cout << "***" << e.what() << "***" << endl; cout << "---->" << line << endl; cout << "boom size:" << list2.size() << " line:"<<line<< " insize:"<<size<<endl; } } /*BOOST_FOREACH(std::string token, stringList) { std::cout << token << '\n'; ; } */ } }
void swd::connection::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) { /** * If an error occurs then no new asynchronous operations are started. This * means that all shared_ptr references to the connection object will disappear * and the object will be destroyed automatically after this handler returns. * The connection class's destructor closes the socket. */ if (e) { return; } /** * Since there was no error we can start parsing the input now. The parser * fills the object request_ with data. */ boost::tribool result; boost::tie(result, boost::tuples::ignore) = request_parser_.parse( request_, buffer_.data(), buffer_.data() + bytes_transferred ); /** * If result is true the complete request is parsed. If it is false there was * an error. If it is indeterminate then the parsing is not complete yet and * the program will read more input and append it to the old request_ object. */ if (indeterminate(result)) { /* Not finished yet with this request, start reading again. */ this->start_read(); /* And don't process the input yet. */ return; } /* The handler used to process the reply. */ swd::reply_handler reply_handler(reply_); try { if (!result) { swd::log::i()->send(swd::warning, "Bad request from " + remote_address_.to_string()); throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } /* Try to add a profile for the request. */ try { swd::profile_ptr profile = swd::database::i()->get_profile( remote_address_.to_string(), request_->get_profile_id() ); request_->set_profile(profile); } catch (swd::exceptions::database_exception& e) { swd::log::i()->send(swd::uncritical_error, e.what()); throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } /* The handler used to process the incoming request. */ swd::request_handler request_handler(request_); /* Only continue processing the reply if it is signed correctly. */ if (!request_handler.valid_signature()) { swd::log::i()->send(swd::warning, "Bad signature from " + remote_address_.to_string()); throw swd::exceptions::connection_exception(STATUS_BAD_SIGNATURE); } /** * Before the request can be processed the input has to be transfered * from the encoded json string to a swd::parameters list. */ if (!request_handler.decode()) { swd::log::i()->send(swd::warning, "Bad json from " + remote_address_.to_string()); throw swd::exceptions::connection_exception(STATUS_BAD_JSON); } /* Process the request. */ std::vector<std::string> threats; try { if (swd::database::i()->is_flooding(request_->get_client_ip(), request_->get_profile_id())) { throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } threats = request_handler.process(); } catch (swd::exceptions::database_exception& e) { swd::log::i()->send(swd::uncritical_error, e.what()); /** * Problems with the database result in a bad request. If protection * is enabled access to the site will not be granted. */ throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } if (!threats.empty()) { reply_->set_threats(threats); reply_->set_status(STATUS_ATTACK); } else { reply_->set_status(STATUS_OK); } } catch(swd::exceptions::connection_exception& e) { reply_->set_status(e.code()); } /* Encode the reply. */ reply_handler.encode(); /* Send the answer to the client. */ if (ssl_) { boost::asio::async_write( ssl_socket_, reply_->to_buffers(), strand_.wrap( boost::bind( &connection::handle_write, shared_from_this(), boost::asio::placeholders::error ) ) ); } else { boost::asio::async_write( socket_, reply_->to_buffers(), strand_.wrap( boost::bind( &connection::handle_write, shared_from_this(), boost::asio::placeholders::error ) ) ); } }
void server_session::handle_read_handshake(const boost::system::error_code& e, std::size_t bytes_transferred) { std::ostringstream line; line << &m_buf; m_raw_client_handshake += line.str(); access_log(m_raw_client_handshake,ALOG_HANDSHAKE); std::vector<std::string> tokens; std::string::size_type start = 0; std::string::size_type end; // Get request and parse headers end = m_raw_client_handshake.find("\r\n",start); while(end != std::string::npos) { tokens.push_back(m_raw_client_handshake.substr(start, end - start)); start = end + 2; end = m_raw_client_handshake.find("\r\n",start); } for (size_t i = 0; i < tokens.size(); i++) { if (i == 0) { m_client_http_request = tokens[i]; } end = tokens[i].find(": ",0); if (end != std::string::npos) { std::string h = tokens[i].substr(0,end); if (get_client_header(h) == "") { m_client_headers[h] = tokens[i].substr(end+2); } else { m_client_headers[h] += ", " + tokens[i].substr(end+2); } } } // handshake error checking try { std::stringstream err; std::string h; // check the method if (m_client_http_request.substr(0,4) != "GET ") { err << "Websocket handshake has invalid method: " << m_client_http_request.substr(0,4); throw(handshake_error(err.str(),400)); } // check the HTTP version // TODO: allow versions greater than 1.1 end = m_client_http_request.find(" HTTP/1.1",4); if (end == std::string::npos) { err << "Websocket handshake has invalid HTTP version"; throw(handshake_error(err.str(),400)); } m_resource = m_client_http_request.substr(4,end-4); // verify the presence of required headers h = get_client_header("Host"); if (h == "") { throw(handshake_error("Required Host header is missing",400)); } else if (!m_server->validate_host(h)) { err << "Host " << h << " is not one of this server's names."; throw(handshake_error(err.str(),400)); } h = get_client_header("Upgrade"); if (h == "") { throw(handshake_error("Required Upgrade header is missing",400)); } else if (!boost::iequals(h,"websocket")) { err << "Upgrade header was " << h << " instead of \"websocket\""; throw(handshake_error(err.str(),400)); } h = get_client_header("Connection"); if (h == "") { throw(handshake_error("Required Connection header is missing",400)); } else if (!boost::ifind_first(h,"upgrade")) { err << "Connection header, \"" << h << "\", does not contain required token \"upgrade\""; throw(handshake_error(err.str(),400)); } if (get_client_header("Sec-WebSocket-Key") == "") { throw(handshake_error("Required Sec-WebSocket-Key header is missing",400)); } h = get_client_header("Sec-WebSocket-Version"); if (h == "") { throw(handshake_error("Required Sec-WebSocket-Version header is missing",400)); } else { m_version = atoi(h.c_str()); if (m_version != 7 && m_version != 8 && m_version != 13) { err << "This server doesn't support WebSocket protocol version " << m_version; throw(handshake_error(err.str(),400)); } } if (m_version < 13) { h = get_client_header("Sec-WebSocket-Origin"); } else { h = get_client_header("Origin"); } if (h != "") { m_client_origin = h; } // TODO: extract subprotocols // TODO: extract extensions // optional headers (delegated to the local interface) if (m_local_interface) { m_local_interface->validate(shared_from_this()); } m_server_http_code = 101; m_server_http_string = "Switching Protocols"; } catch (const handshake_error& e) { std::stringstream err; err << "Caught handshake exception: " << e.what(); access_log(e.what(),ALOG_HANDSHAKE); log(err.str(),LOG_ERROR); m_server_http_code = e.m_http_error_code; m_server_http_string = e.m_http_error_msg; } write_handshake(); }
void tcp_socket_session::handle_async_read( const boost::system::error_code& error, std::size_t bytes_transferred) { if (error) { if (error == boost::asio::error::operation_aborted || !peer_sock.is_open()) { return; } terminate(); if (error != boost::asio::error::eof && error != boost::asio::error::connection_reset) { std::cout << "TCP read error: " << error.message() << std::endl; } return; } if ((std::chrono::steady_clock::now() - timeout_timestamp) >= tcp_socket_session::TIMEOUT_LENGTH) { netstring_buffer.clear(); } netstring_buffer.append(buffer.begin(), buffer.begin()+bytes_transferred); int netstring_length; std::string parsed_message; while (netstring_buffer.length() > 0) { try { netstring_length = utils::netstring::parse(netstring_buffer, parsed_message); } catch (utils::netstring_error& error) { write(error.what()); netstring_buffer.clear(); break; } // Zero or more bytes have been processed if (netstring_length >= 0) { try { msg_center->process(this_session, parsed_message); } catch (const messaging::session_interface::process_error& e) { std::cout << "Error processing incoming message: "; std::cout << e.what() << std::endl; } netstring_buffer.erase(0, netstring_length); } // More bytes are needed to process a valid string else { break; } } if (netstring_buffer.length() > 0) { timeout_timestamp = std::chrono::steady_clock::now(); } start_async_read(); }
void AsioServer::handleAccept(const boost::system::error_code& e){ LOG_DEBUG("AsioServer::handleAccept => accept a connection"); ConnectionPtr acceptConnection = newConnection_; newConnection_ = newConnection(); acceptor_.async_accept(newConnection_->getSocket(), boost::bind(&AsioServer::handleAccept, this, boost::asio::placeholders::error)); LOG_DEBUG("AsioServer::handleAccept => wait a new connection : cid = %d" , newConnection_->getId()); if(!e){ try{ acceptConnection->open(); LOG_DEBUG("AsioServer::handleAccept => new connection start : cid = %d" , acceptConnection->getId()); } catch (exception &e){ LOG_ERROR("AsioServer::handleAccept => new connection start error : what = %s" , e.what()); } } else { LOG_ERROR("AsioServer::handleAccept => error : " , e.message().c_str()); } }
void swd::connection::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) { /** * If an error occurs then no new asynchronous operations are started. This * means that all shared_ptr references to the connection object will disappear * and the object will be destroyed automatically after this handler returns. * The connection class's destructor closes the socket. */ if (e) { return; } /** * Since there was no error we can start parsing the input now. The parser * fills the object request_ with data. */ boost::tribool result; boost::tie(result, boost::tuples::ignore) = request_parser_.parse( request_, buffer_.data(), buffer_.data() + bytes_transferred ); /** * If result is true the complete request is parsed. If it is false there was * an error. If it is indeterminate then the parsing is not complete yet and * the program will read more input and append it to the old request_ object. */ if (indeterminate(result)) { /* Not finished yet with this request, start reading again. */ this->start_read(); /* And don't process the input yet. */ return; } /* The handler used to process the reply. */ swd::reply_handler reply_handler(reply_); try { if (!result) { swd::log::i()->send(swd::warning, "Bad request from " + remote_address_.to_string()); throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } /* Try to add a profile for the request. */ try { swd::profile_ptr profile = database_->get_profile( remote_address_.to_string(), request_->get_profile_id() ); request_->set_profile(profile); } catch (swd::exceptions::database_exception& e) { swd::log::i()->send(swd::uncritical_error, e.what()); throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } /* The handler used to process the incoming request. */ swd::request_handler request_handler(request_, cache_, storage_); /* Only continue processing the reply if it is signed correctly. */ if (!request_handler.valid_signature()) { swd::log::i()->send(swd::warning, "Bad signature from " + remote_address_.to_string()); throw swd::exceptions::connection_exception(STATUS_BAD_SIGNATURE); } /** * Before the request can be processed the input has to be transfered * from the encoded json string to a swd::parameters list. */ if (!request_handler.decode()) { swd::log::i()->send(swd::warning, "Bad json from " + remote_address_.to_string()); throw swd::exceptions::connection_exception(STATUS_BAD_JSON); } /* Check profile for outdated cache. */ swd::profile_ptr profile = request_->get_profile(); if (profile->is_cache_outdated()) { cache_->reset(profile->get_id()); } /* Process the request. */ std::vector<std::string> threats; try { swd::parameters parameters = request_->get_parameters(); /** * Check security limitations first. */ int max_params = swd::config::i()->get<int>("max-parameters"); if ((max_params > -1) && (parameters.size() > max_params)) { swd::log::i()->send(swd::notice, "Too many parameters"); throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } int max_length_path = swd::config::i()->get<int>("max-length-path"); int max_length_value = swd::config::i()->get<int>("max-length-value"); if ((max_length_path > -1) || (max_length_value > -1)) { for (swd::parameters::iterator it_parameter = parameters.begin(); it_parameter != parameters.end(); it_parameter++) { swd::parameter_ptr parameter(*it_parameter); if ((max_length_path > -1) && (parameter->get_path().length() > max_length_path)) { swd::log::i()->send(swd::notice, "Too long parameter path"); throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } if ((max_length_value > -1) && (parameter->get_value().length() > max_length_value)) { swd::log::i()->send(swd::notice, "Too long parameter value"); throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } } } if (profile->is_flooding_enabled()) { if (database_->is_flooding(request_->get_client_ip(), profile->get_id())) { swd::log::i()->send(swd::notice, "Too many requests"); throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } } /* Time to analyze the request. */ request_handler.process(); } catch (swd::exceptions::database_exception& e) { swd::log::i()->send(swd::uncritical_error, e.what()); /** * Problems with the database result in a bad request. If protection * is enabled access to the site will not be granted. */ throw swd::exceptions::connection_exception(STATUS_BAD_REQUEST); } if (profile->get_mode() == MODE_ACTIVE) { if (request_->is_threat()) { reply_->set_status(STATUS_CRITICAL_ATTACK); } else if (request_->has_threats()) { reply_->set_threats(request_handler.get_threats()); reply_->set_status(STATUS_ATTACK); } else { reply_->set_status(STATUS_OK); } } else { reply_->set_status(STATUS_OK); } } catch(swd::exceptions::connection_exception& e) { if (!request_->get_profile()) { reply_->set_status(STATUS_BAD_REQUEST); } else if (request_->get_profile()->get_mode() == MODE_ACTIVE) { reply_->set_status(e.code()); } else { reply_->set_status(STATUS_OK); } } /* Encode the reply. */ reply_handler.encode(); /* Send the answer to the client. */ if (ssl_) { boost::asio::async_write( ssl_socket_, reply_->to_buffers(), strand_.wrap( boost::bind( &connection::handle_write, shared_from_this(), boost::asio::placeholders::error ) ) ); } else { boost::asio::async_write( socket_, reply_->to_buffers(), strand_.wrap( boost::bind( &connection::handle_write, shared_from_this(), boost::asio::placeholders::error ) ) ); } }
void connection::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred) { if (!e) { if (bytes_transferred != size) { this->client_->m_main->consoleLogger->information(Poco::format("Did not receive proper amount of bytes : rcv: %?d needed: %?d", bytes_transferred, size)); server.stop(shared_from_this()); return; } char * t = buffer_.data(); if ((*(int8_t*)t != 0x0a) && (*(int8_t*)(t+1) != 0x0b) && (*(int8_t*)(t+2) != 0x01)) { server.consoleLogger->information(Poco::format("Not an AMF3 object - ip:%s", address)); server.stop(shared_from_this()); return; } //printf("uid("XI64")\n", uid); // read object size if ((size > MAXPACKETSIZE) || (size <= 0)) { //ERROR - object too large - close connection server.stop(shared_from_this()); return; } //TODO: Decision: have socket read thread handle packets, or push into a queue //socket thread (easy, already done) // PRO: typically instant response times due to it being processed as it comes in // CON: a large request (legit or non) would cause the socket read thread to lag // //process thread (complex, ideally better) // PRO: can alleviate lag on socket threads and create multiple thread processing queues depending on importance // CON: complexity and large requests would typically land in the same thread (causing even more lag for them) unless // made even more complex to have multiple threads for large requests // //Option 3: Evony style // -- create a process thread per x amount of sockets // PRO: lag from one client only affects a set amount of players and not the entire server // CON: quite complex. is ultimately the process thread option only for x amount of sockets // parse packet request_.size = size; amf3parser * cparser = new amf3parser(buffer_.data()); try { request_.object = cparser->ReadNextObject(); delete cparser; } catch (...) { std::cerr << "uncaught handle_request()::amf3parser exception\n"; } request_.conn = this; try { request_handler_.handle_request(request_, reply_); } catch (std::exception& e) { std::cerr << "handle_request() exception: " << e.what() << "\n"; } // if (reply_.objects.size() > 0) // { // // send reply packets // try { // socket_.write_some(reply_.to_buffers()); // } // catch (std::exception& e) // { // std::cerr << "asio::write_some() exception: " << e.what() << "\n"; // } // reply_.objects.clear(); // } boost::asio::async_read(socket_, boost::asio::buffer(buffer_, 4), boost::bind(&connection::handle_read_header, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } else if (e != boost::asio::error::operation_aborted) { server.stop(shared_from_this()); return; } }