void parser::parse_spdy_rst_stream(boost::system::error_code &ec, const spdy_control_frame_info& frame) { boost::uint32_t stream_id = 0; boost::uint32_t status_code = 0; // First complete the check for size and flag // The flag for RST frame should be 0, The length should be 8 if(frame.flags != 0 || frame.length != 8 ){ return; } // Get the 31 bit stream id boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr); stream_id = four_bytes & 0x7FFFFFFF; m_read_ptr += 4; // Get the status code status_code = algorithm::to_uint32(m_read_ptr); char const* const status_code_str = rst_stream_status(status_code); if(status_code_str){ PION_LOG_INFO(m_logger, "SPDY Status Code is : " << status_code_str); }else{ PION_LOG_INFO(m_logger, "SPDY RST Invalid status code : " << status_code); } }
void PionOneToOneScheduler::startup(void) { // lock mutex for thread safety boost::mutex::scoped_lock scheduler_lock(m_mutex); if (! m_is_running) { PION_LOG_INFO(m_logger, "Starting thread scheduler"); m_is_running = true; // make sure there are enough services initialized while (m_service_pool.size() < m_num_threads) { boost::shared_ptr<ServicePair> service_ptr(new ServicePair()); m_service_pool.push_back(service_ptr); } // schedule a work item for each service to make sure that it doesn't complete for (ServicePool::iterator i = m_service_pool.begin(); i != m_service_pool.end(); ++i) { keepRunning((*i)->first, (*i)->second); } // start multiple threads to handle async tasks for (boost::uint32_t n = 0; n < m_num_threads; ++n) { boost::shared_ptr<boost::thread> new_thread(new boost::thread( boost::bind(&PionScheduler::processServiceWork, this, boost::ref(m_service_pool[n]->first)) )); m_thread_pool.push_back(new_thread); } } }
void server::remove_resource(const std::string& resource) { std::unique_lock<std::mutex> resource_lock(m_resource_mutex, std::try_to_lock); const std::string clean_resource(strip_trailing_slash(resource)); m_resources.erase(clean_resource); PION_LOG_INFO(m_logger, "Removed request handler for HTTP resource: " << clean_resource); }
void HTTPServer::removeResource(const std::string& resource) { boost::mutex::scoped_lock resource_lock(m_resource_mutex); const std::string clean_resource(stripTrailingSlash(resource)); m_resources.erase(clean_resource); PION_LOG_INFO(m_logger, "Removed request handler for HTTP resource: " << clean_resource); }
void plugin_server::set_service_option(const std::string& resource, const std::string& name, const std::string& value) { const std::string clean_resource(strip_trailing_slash(resource)); m_services.run(clean_resource, boost::bind(&http::plugin_service::set_option, _1, name, value)); PION_LOG_INFO(m_logger, "Set web service option for resource (" << resource << "): " << name << '=' << value); }
void server::add_resource(const std::string& resource, request_handler_t request_handler) { std::unique_lock<std::mutex> resource_lock(m_resource_mutex, std::try_to_lock); const std::string clean_resource(strip_trailing_slash(resource)); m_resources.insert(std::make_pair(clean_resource, request_handler)); PION_LOG_INFO(m_logger, "Added request handler for HTTP resource: " << clean_resource); }
void HTTPServer::addResource(const std::string& resource, RequestHandler request_handler) { boost::mutex::scoped_lock resource_lock(m_resource_mutex); const std::string clean_resource(stripTrailingSlash(resource)); m_resources.insert(std::make_pair(clean_resource, request_handler)); PION_LOG_INFO(m_logger, "Added request handler for HTTP resource: " << clean_resource); }
void plugin_server::load_service(const std::string& resource, const std::string& service_name) { const std::string clean_resource(strip_trailing_slash(resource)); http::plugin_service *service_ptr; service_ptr = m_services.load(clean_resource, service_name); http::server::add_resource(clean_resource, boost::ref(*service_ptr)); service_ptr->set_resource(clean_resource); PION_LOG_INFO(m_logger, "Loaded web service plug-in for resource (" << clean_resource << "): " << service_name); }
void plugin_server::add_service(const std::string& resource, http::plugin_service *service_ptr) { plugin_ptr<http::plugin_service> plugin_ptr; const std::string clean_resource(strip_trailing_slash(resource)); service_ptr->set_resource(clean_resource); m_services.add(clean_resource, service_ptr); http::server::add_resource(clean_resource, boost::ref(*service_ptr)); PION_LOG_INFO(m_logger, "Loaded static web service for resource (" << clean_resource << ")"); }
void server::add_redirect(const std::string& requested_resource, const std::string& new_resource) { std::unique_lock<std::mutex> resource_lock(m_resource_mutex, std::try_to_lock); const std::string clean_requested_resource(strip_trailing_slash(requested_resource)); const std::string clean_new_resource(strip_trailing_slash(new_resource)); m_redirects.insert(std::make_pair(clean_requested_resource, clean_new_resource)); PION_LOG_INFO(m_logger, "Added redirection for HTTP resource " << clean_requested_resource << " to resource " << clean_new_resource); }
void HTTPServer::addRedirect(const std::string& requested_resource, const std::string& new_resource) { boost::mutex::scoped_lock resource_lock(m_resource_mutex); const std::string clean_requested_resource(stripTrailingSlash(requested_resource)); const std::string clean_new_resource(stripTrailingSlash(new_resource)); m_redirects.insert(std::make_pair(clean_requested_resource, clean_new_resource)); PION_LOG_INFO(m_logger, "Added redirection for HTTP resource " << clean_requested_resource << " to resource " << clean_new_resource); }
void PionScheduler::shutdown(void) { // lock mutex for thread safety boost::mutex::scoped_lock scheduler_lock(m_mutex); if (m_is_running) { PION_LOG_INFO(m_logger, "Shutting down the thread scheduler"); while (m_active_users > 0) { // first, wait for any active users to exit PION_LOG_INFO(m_logger, "Waiting for " << m_active_users << " scheduler users to finish"); m_no_more_active_users.wait(scheduler_lock); } // shut everything down m_is_running = false; stopServices(); stopThreads(); finishServices(); finishThreads(); PION_LOG_INFO(m_logger, "The thread scheduler has shutdown"); // Make sure anyone waiting on shutdown gets notified m_scheduler_has_stopped.notify_all(); } else { // stop and finish everything to be certain that no events are pending stopServices(); stopThreads(); finishServices(); finishThreads(); // Make sure anyone waiting on shutdown gets notified // even if the scheduler did not startup successfully m_scheduler_has_stopped.notify_all(); } }
void parser::parse_spdy_ping_frame(boost::system::error_code &ec, const spdy_control_frame_info& frame) { // First complete the check for size // The length should be 4 always if(frame.length != 4){ return; } boost::uint32_t ping_id = 0; // Get the 32 bit ping id ping_id = algorithm::to_uint32(m_read_ptr); m_read_ptr += 4; PION_LOG_INFO(m_logger, "SPDY " << "Ping ID is : " << ping_id); }
void PionSingleServiceScheduler::startup(void) { // lock mutex for thread safety boost::mutex::scoped_lock scheduler_lock(m_mutex); if (! m_is_running) { PION_LOG_INFO(m_logger, "Starting thread scheduler"); m_is_running = true; // schedule a work item to make sure that the service doesn't complete m_service.reset(); keepRunning(m_service, m_timer); // start multiple threads to handle async tasks for (boost::uint32_t n = 0; n < m_num_threads; ++n) { boost::shared_ptr<boost::thread> new_thread(new boost::thread( boost::bind(&PionScheduler::processServiceWork, this, boost::ref(m_service)) )); m_thread_pool.push_back(new_thread); } } }
void parser::parse_spdy_goaway_frame(boost::system::error_code &ec, const spdy_control_frame_info& frame) { // First complete the check for size // The length should be 4 always if(frame.length != 4){ return; } boost::uint32_t last_good_stream_id = 0; boost::uint32_t status_code = 0; // Get the 31 bit stream id boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr); last_good_stream_id = four_bytes & 0x7FFFFFFF; m_read_ptr += 4; // Get the status code status_code = algorithm::to_uint32(m_read_ptr); // Chek if there was an error if(status_code == 1){ PION_LOG_ERROR(m_logger, "There was a Protocol Error"); set_error(ec, ERROR_PROTOCOL_ERROR); return; }else if (status_code == 11) { PION_LOG_ERROR(m_logger, "There was an Internal Error"); set_error(ec, ERROR_INTERNAL_SPDY_ERROR); return; } PION_LOG_INFO(m_logger, "SPDY " << "Status Code is : " << status_code); }
void HTTPServer::handleRequest(HTTPRequestPtr& http_request, TCPConnectionPtr& tcp_conn) { if (! http_request->isValid()) { // the request is invalid or an error occured PION_LOG_INFO(m_logger, "Received an invalid HTTP request"); m_bad_request_handler(http_request, tcp_conn); return; } PION_LOG_DEBUG(m_logger, "Received a valid HTTP request"); // strip off trailing slash if the request has one std::string resource_requested(stripTrailingSlash(http_request->getResource())); // apply any redirection RedirectMap::const_iterator it = m_redirects.find(resource_requested); unsigned int num_redirects = 0; while (it != m_redirects.end()) { if (++num_redirects > MAX_REDIRECTS) { PION_LOG_ERROR(m_logger, "Maximum number of redirects (HTTPServer::MAX_REDIRECTS) exceeded for requested resource: " << http_request->getOriginalResource()); m_server_error_handler(http_request, tcp_conn, "Maximum number of redirects (HTTPServer::MAX_REDIRECTS) exceeded for requested resource"); return; } resource_requested = it->second; http_request->changeResource(resource_requested); it = m_redirects.find(resource_requested); } // if authentication activated, check current request if (m_auth) { // try to verify authentication if (! m_auth->handleRequest(http_request, tcp_conn)) { // the HTTP 401 message has already been sent by the authentication object PION_LOG_DEBUG(m_logger, "Authentication required for HTTP resource: " << resource_requested); if (http_request->getResource() != http_request->getOriginalResource()) { PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource()); } return; } } // search for a handler matching the resource requested RequestHandler request_handler; if (findRequestHandler(resource_requested, request_handler)) { // try to handle the request try { request_handler(http_request, tcp_conn); PION_LOG_DEBUG(m_logger, "Found request handler for HTTP resource: " << resource_requested); if (http_request->getResource() != http_request->getOriginalResource()) { PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource()); } } catch (HTTPResponseWriter::LostConnectionException& e) { // the connection was lost while or before sending the response PION_LOG_WARN(m_logger, "HTTP request handler: " << e.what()); tcp_conn->setLifecycle(TCPConnection::LIFECYCLE_CLOSE); // make sure it will get closed tcp_conn->finish(); } catch (std::bad_alloc&) { // propagate memory errors (FATAL) throw; } catch (std::exception& e) { // recover gracefully from other exceptions thrown request handlers PION_LOG_ERROR(m_logger, "HTTP request handler: " << e.what()); m_server_error_handler(http_request, tcp_conn, e.what()); } } else { // no web services found that could handle the request PION_LOG_INFO(m_logger, "No HTTP request handlers found for resource: " << resource_requested); if (http_request->getResource() != http_request->getOriginalResource()) { PION_LOG_DEBUG(m_logger, "Original resource requested was: " << http_request->getOriginalResource()); } m_not_found_handler(http_request, tcp_conn); } }