Exemplo n.º 1
0
void PionScheduler::processServiceWork(boost::asio::io_service& service) {
	while (m_is_running) {
		try {
			service.run();
		} catch (std::exception& e) {
			PION_LOG_ERROR(m_logger, e.what());
		} catch (...) {
			PION_LOG_ERROR(m_logger, "caught unrecognized exception");
		}
	}	
}
Exemplo n.º 2
0
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);
    
}
Exemplo n.º 3
0
	/**
	 * public function to process a new Event.  checks to make sure the reactor
	 * is running, increments "events in" counter, and ensures configuration
	 * data is not being changed before calling the virtual process() function
	 *
	 * @param e pointer to the Event to process
	 */
	inline void operator()(const EventPtr& e) {
		if ( isRunning() ) {
			ConfigReadLock cfg_lock(*this);
			// re-check after locking
			if ( isRunning() ) {
				++m_events_in;
				try {
					process(e);
				} catch (std::exception& e) {
					PION_LOG_ERROR(m_logger, "reactor_id: " << getId() << " - " << e.what() << " - rethrowing");
					throw;
				}
			}
		}
	}
Exemplo n.º 4
0
void TransformReactor::process(const EventPtr& e)
{
	EventPtr new_e;
	// Create new event; either same type (if UNDEFINED) or defined type
	m_event_factory.create(new_e, m_event_type == Vocabulary::UNDEFINED_TERM_REF ? e->getType() : m_event_type);

	// Copy terms over from original
	switch (m_copy_original) {
		case COPY_ALL:				// Copy all terms over from original event
			*new_e += *e;
			break;
		case COPY_UNCHANGED:		// Copy ONLY terms, that are not defined in transformations...
			*new_e += *e;			// First copy all terms...
			// Then remove all the ones with transformations...
			for (TransformChain::iterator i = m_transforms.begin(); i != m_transforms.end(); i++)
				(*i)->removeTerm(new_e);
			// TODO: Which is more efficient? Only copying the ones that are not transformed, or this?
			break;
		case COPY_NONE:				// Do not copy terms from original event
			break;
	}

	try {
		for (TransformChain::iterator i = m_transforms.begin(); i != m_transforms.end(); i++)
			(*i)->transform(new_e, e);		// transform   d <- s
	} catch (std::exception& e) {
		// Likely Boost.regex throw
		PION_LOG_ERROR(m_logger, "reactor_id: " << getId() << " - " << e.what() << " - handled");
	}

	deliverEvent(new_e);			// Deliver the modified event

	// Transformation is done, deliver original event?
	if (m_deliver_original != DO_NEVER)
	 	deliverEvent(e);
}
Exemplo n.º 5
0
void parser::parse_header_payload(boost::system::error_code &ec,
                                  decompressor_ptr& decompressor,
                                  const spdy_control_frame_info& frame,
                                  http_protocol_info& http_info,
                                  boost::uint32_t current_stream_count)
{
    boost::uint32_t stream_id = 0;
    boost::uint32_t associated_stream_id;
    boost::uint32_t header_block_length = frame.length;
    
    // 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;
    
    http_info.stream_id = stream_id;
    
    // Get SYN_STREAM-only fields.
    
    if (frame.type == SPDY_SYN_STREAM) {
        
        // Get associated stream ID.
        
        boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
        associated_stream_id = four_bytes & 0x7FFFFFFF;
        
        m_read_ptr += 4;
        
        // The next bits are priority, unused, and slot.
        // Disregard these for now as we dont need them
        
        m_read_ptr +=2 ;
        
    } else if( frame.type == SPDY_SYN_REPLY || frame.type == SPDY_HEADERS ) {
        
        // Unused bits
        m_read_ptr +=2 ;
    }
    
    // Get our header block length.
    
    switch (frame.type) {
        case SPDY_SYN_STREAM:
            header_block_length -= 10;
            break;
        case SPDY_SYN_REPLY:
        case SPDY_HEADERS:
            // This is a very important distinction.
            // It should be 6 bytes for SPDYv2 and 4 bytes for SPDYv3.
            header_block_length -= 6;
            break;
        default:
            // Unhandled case. This should never happen.
            PION_LOG_ERROR(m_logger, "Invalid SPDY Frame Type");
            set_error(ec, ERROR_INVALID_SPDY_FRAME);
            return;
    }
    
    // Decompress header block as necessary.
    m_uncompressed_ptr = decompressor->decompress(m_read_ptr,
                                                  stream_id,
                                                  frame,
                                                  header_block_length);
    
    if (!m_uncompressed_ptr) {
        set_error(ec, ERROR_DECOMPRESSION);
        return;
    }
        
    // Now parse the name/value pairs
    
    // The number of name/value pairs is 16 bit SPDYv2
    // and it is 32 bit in SPDYv3
    
    // TBD : Add support for SPDYv3
    boost::uint16_t num_name_val_pairs = algorithm::to_uint16(m_uncompressed_ptr);
    
    m_uncompressed_ptr += 2;
    
    std::string content_type = "";
    std::string content_encoding = "";
    
    for(boost::uint16_t count = 0; count < num_name_val_pairs; ++count){
        
        
        // Get the length of the name
        boost::uint16_t length_name = algorithm::to_uint16(m_uncompressed_ptr);
        std::string name = "";
        
        m_uncompressed_ptr += 2;
        
        {
            for(boost::uint16_t count = 0; count < length_name; ++count){
                name.push_back(*(m_uncompressed_ptr+count));
            }
            m_uncompressed_ptr += length_name;
        }
        
        // Get the length of the value
        boost::uint16_t length_value = algorithm::to_uint16(m_uncompressed_ptr);
        std::string value = "";
        
        m_uncompressed_ptr += 2;
        
        {
            for(boost::uint16_t count = 0; count < length_value; ++count){
                value.push_back(*(m_uncompressed_ptr+count));
            }
            m_uncompressed_ptr += length_value;
        }
        
        // Save these headers
        http_info.http_headers.insert(std::make_pair(name, value));
    }
}
Exemplo n.º 6
0
bool parser::populate_frame(boost::system::error_code& ec,
                            spdy_control_frame_info& frame,
                            boost::uint32_t& length_packet,
                            boost::uint32_t& stream_id,
                            http_protocol_info& http_info)
{
    // Get the control bit
    boost::uint8_t control_bit;
    boost::uint16_t byte_value = algorithm::to_uint16(m_read_ptr);
    control_bit = byte_value >> (sizeof(short) * CHAR_BIT - 1);
    
    frame.control_bit = (control_bit != 0);
    
    if(control_bit){
        
        // Control bit is set; This is a control frame
        
        // Get the version number
        boost::uint16_t two_bytes = algorithm::to_uint16(m_read_ptr);
        frame.version = two_bytes & 0x7FFF;
        
        // Increment the read pointer
        m_read_ptr += 2;
        length_packet -= 2;
        http_info.data_offset +=2;
        
        // Get the type
        frame.type = algorithm::to_uint16(m_read_ptr);
        
        if (frame.type >= SPDY_INVALID) {
            // SPDY Frame is invalid
            
            // This is not a SPDY frame, throw an error
            PION_LOG_ERROR(m_logger, "Invalid SPDY Frame");
            set_error(ec, ERROR_INVALID_SPDY_FRAME);
            return false;
        }
    }else {
        
        // Control bit is not set; This is a data frame
        
        frame.type = SPDY_DATA;
        frame.version = 0; /* Version doesn't apply to DATA. */
        // Get the stream id
        boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
        stream_id = four_bytes & 0x7FFFFFFF;
        
        http_info.stream_id = stream_id;
        
        m_read_ptr +=2;
        http_info.data_offset +=2;
        length_packet -= 2;
        
    }
    
    // Increment the read pointer
    m_read_ptr += 2;
    length_packet -= 2;
    http_info.data_offset +=2;
    
    // Get the flags
    frame.flags = (boost::uint8_t)*m_read_ptr;
    
    // Increment the read pointer
    
    // Get the length
    boost::uint32_t four_bytes = algorithm::to_uint32(m_read_ptr);
    frame.length = four_bytes & 0xFFFFFF;
    
    // Increment the read pointer
    m_read_ptr += 4;
    length_packet -= 4;
    http_info.data_offset +=4;
    
    http_info.data_size = frame.length;
    
    if(control_bit){
        four_bytes = algorithm::to_uint32(m_read_ptr);
        stream_id = four_bytes & 0x7FFFFFFF;
    }
    
    return true;
}
Exemplo n.º 7
0
boost::tribool parser::parse_spdy_frame(boost::system::error_code& ec,
                                        decompressor_ptr& decompressor,
                                        http_protocol_info& http_info,
                                        boost::uint32_t& length_packet,
                                        boost::uint32_t current_stream_count)
{
    boost::tribool rc = true;
    
    // Verify that this is a spdy frame
    
    BOOST_ASSERT(m_read_ptr);
    boost::uint8_t first_byte = (boost::uint8_t)*m_read_ptr;
    if (first_byte != 0x80 && first_byte != 0x0) {
        // This is not a SPDY frame, throw an error
        PION_LOG_ERROR(m_logger, "Invalid SPDY Frame");
        set_error(ec, ERROR_INVALID_SPDY_FRAME);
        return false;
    }
    
    boost::uint8_t              control_bit;
    spdy_control_frame_info     frame;
    boost::uint32_t             stream_id = 0;
    
    ec.clear();

    // Populate the frame
    bool populate_frame_result = populate_frame(ec, frame, length_packet, stream_id, http_info);
    
    if(!populate_frame_result){
        /// There was an error; No need to further parse.
        return false;
    }
    
    BOOST_ASSERT(stream_id != 0);
    
    control_bit = (boost::uint8_t)frame.control_bit;
    
    // There is a possibility that there are more than one SPDY frames in one TCP frame
    if(length_packet > frame.length){
        m_current_data_chunk_ptr = m_read_ptr + frame.length;
        length_packet -= frame.length;
        rc = boost::indeterminate;
    }
    
    if (!control_bit) {
        // Parse the data packet
        parse_spdy_data(ec, frame, stream_id, http_info);
    }
    
    /* Abort here if the version is too low. */
    
    if (frame.version > MIN_SPDY_VERSION) {
        // Version less that min SPDY version, throw an error
        PION_LOG_ERROR(m_logger, "Invalid SPDY Version Number");
        set_error(ec, ERROR_INVALID_SPDY_VERSION);
        return false;
    }
    
    if(frame.type ==  SPDY_SYN_STREAM){
        http_info.http_type = HTTP_REQUEST;
    }else if (frame.type == SPDY_SYN_REPLY){
        http_info.http_type = HTTP_RESPONSE;
    }else if (frame.type == SPDY_DATA){
        http_info.http_type = HTTP_DATA;
    }

    switch (frame.type) {
        case SPDY_SYN_STREAM:
        case SPDY_SYN_REPLY:
        case SPDY_HEADERS:
            parse_header_payload(ec, decompressor, frame, http_info, current_stream_count);
            break;
            
        case SPDY_RST_STREAM:
            parse_spdy_rst_stream(ec, frame);
            http_info.http_type = SPDY_CONTROL;
            break;
            
        case SPDY_SETTINGS:
            parse_spdy_settings_frame(ec, frame);
            http_info.http_type = SPDY_CONTROL;
            break;
            
        case SPDY_PING:
            parse_spdy_ping_frame(ec, frame);
            http_info.http_type = SPDY_CONTROL;
            break;
            
        case SPDY_GOAWAY:
            parse_spdy_goaway_frame(ec, frame);
            http_info.http_type = SPDY_CONTROL;
            break;
            
        case SPDY_WINDOW_UPDATE:
            parse_spdy_window_update_frame(ec, frame);
            http_info.http_type = SPDY_CONTROL;
            break;
            
        case SPDY_CREDENTIAL:
            // We dont need to parse this for now
            http_info.http_type = SPDY_CONTROL;
            break;
            
        default:
            break;
    }
    
    if (ec)
        return false;
    
    m_last_data_chunk_ptr = m_read_ptr;
    m_read_ptr = m_current_data_chunk_ptr;
    
    return rc;
}
Exemplo n.º 8
0
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);
	}
}