<commit_before>

#include <pedsim_simulator/scene.h>

#include <pedsim_simulator/simulator.h>

#include <pedsim_simulator/element/agentcluster.h>

#include <QApplication>

Simulator::Simulator(const ros::NodeHandle &node)
	: nh_(node)
{
	// nothing to do here
}

Simulator::~Simulator()
{

}

bool Simulator::initializeSimulation()
{
	/// setup ros publishers
	pub_agent_visuals_ = nh_.advertise<visualization_msgs::MarkerArray> ( "agents_markers", 0 );
    pub_group_centers_ = nh_.advertise<visualization_msgs::Marker> ( "group_centers", 0 );
    pub_group_lines_ = nh_.advertise<visualization_msgs::Marker> ( "group_lines", 0 );
    pub_obstacles_ = nh_.advertise<nav_msgs::GridCells> ( "static_obstacles", 0 );
    pub_walls_ = nh_.advertise<visualization_msgs::Marker> ( "walls", 0 );
	pub_all_agents_ = nh_.advertise<pedsim_msgs::AllAgentsState> ( "dynamic_obstacles", 0 );
	pub_attractions_ = nh_.advertise<visualization_msgs::Marker> ( "attractions", 0 );
	pub_queues_ = nh_.advertise<visualization_msgs::Marker> ( "queues", 0 );

	/// setup any pointers
	orientation_handler_.reset ( new OrientationHandler() );

	/// subscribers
    sub_robot_command_ = nh_.subscribe ( "robot_state", 1, &Simulator::callbackRobotCommand, this );

	/// load parameters
    std::string scene_file_param;
    ros::param::param<std::string> ( "/simulator/scene_file", scene_file_param, "scene.xml" );
    // load scenario file
	// TODO - convert qstrings to std::strings
    QString scenefile = QString::fromStdString ( scene_file_param );

	ScenarioReader scenarioReader;
	bool readResult = scenarioReader.readFromFile(scenefile);
	if(readResult == false) {
		ROS_WARN ( "Could not load the scene file, check paths" );
		return false;
	}

    ROS_INFO ( "Loading from %s scene file", scene_file_param.c_str() );

	robot_ = nullptr;

	return true;
}

void Simulator::runSimulation()
{
	// setup the robot
    BOOST_FOREACH ( Agent* a, SCENE.getAgents() )
    {
		// TODO - convert back to robot type enum
        if ( a->getType() == 2 )
            robot_ = a;
    }

    ros::Rate r ( 30 ); // Hz

    while ( ros::ok() )
    {
		SCENE.moveAllAgents();

		publishAgentVisuals();

        publishGroupVisuals();

        // visuals for walls
        publishWalls();

        // only publish the obstacles in the beginning
        if ( SCENE.getTime() < 100 )
		{
            publishObstacles();
// 			publishAttractions();
		}

        ros::spinOnce();

        r.sleep();
    }
}

/// -----------------------------------------------------------------
/// \brief callbackRobotCommand
/// \details Control the robot based on the set velocity command
/// Listens to incoming messages and manipulates the robot.
/// \param[in] msg Message containing the pos and vel for the robot
/// -----------------------------------------------------------------
void Simulator::callbackRobotCommand ( const pedsim_msgs::AgentState::ConstPtr &msg )
{
    double vx = msg->velocity.x;
    double vy = msg->velocity.y;

//     if ( CONFIG.robot_mode == TELEOPERATION )
//         robot_->setteleop ( true );

    if ( robot_->getType() == msg->type )
    {
        if ( robot_->getTeleop() == false )
        {
            robot_->setvx ( vx );
            robot_->setvy ( vy );
            robot_->setVmax ( sqrt ( vx * vx + vy * vy ) );
        }
        else
        {
            robot_->setvx ( vx );
            robot_->setvy ( vy );
            robot_->setVmax ( sqrt ( vx * vx + vy * vy ) );
        }
    }
}

/// -----------------------------------------------------------------
/// \brief publishAgentVisuals
/// \details publish agent status information and the visual markers
/// -----------------------------------------------------------------
void Simulator::publishAgentVisuals()
{
    // minor optimization with arrays for speedup
    visualization_msgs::MarkerArray marker_array;

	// status message
	pedsim_msgs::AllAgentsState all_status;
    std_msgs::Header all_header;
    all_header.stamp = ros::Time::now();
    all_status.header = all_header;

    BOOST_FOREACH ( Agent* a, SCENE.getAgents() )
    {
		/// visual marker message
        visualization_msgs::Marker marker;
        marker.header.frame_id = "world";
        marker.header.stamp = ros::Time();
        marker.ns = "pedsim";
        marker.id = a->getId();

        marker.type = visualization_msgs::Marker::CYLINDER;
// 		marker.type = visualization_msgs::Marker::MESH_RESOURCE;
//         marker.mesh_resource = "package://pedsim_simulator/images/zoey/girl.dae";

		marker.action = 0;  // add or modify

		marker.scale.x = 0.3 / 2.0;
        marker.scale.y = 0.3;
        marker.scale.z = 1.75;

        marker.color.a = 1.0;
        marker.color.r = 0.0;
        marker.color.g = 0.7;
        marker.color.b = 1.0;

        marker.pose.position.z = marker.scale.z / 2.0;
        marker.pose.position.x = a->getx();
        marker.pose.position.y = a->gety();

        if ( a->getStateMachine()->getCurrentState() == AgentStateMachine::AgentState::StateQueueing)
        {
            marker.color.a = 1.0;
            marker.color.r = 1.0;
            marker.color.g = 0.0;
            marker.color.b = 1.0;
        }

        if ( a->getvx() != 0.0 )
        {
            // construct the orientation quaternion
            double theta = atan2 ( a->getvy(), a->getvx() );
            Eigen::Quaternionf q = orientation_handler_->angle2Quaternion ( theta
                                                                          );
            marker.pose.orientation.x = q.x();
            marker.pose.orientation.y = q.y();
            marker.pose.orientation.z = q.z();
            marker.pose.orientation.w = q.w();
        }
        else
        {
            marker.pose.orientation.x = 0.0;
            marker.pose.orientation.y = 0.0;
            marker.pose.orientation.z = 0.0;
            marker.pose.orientation.w = 1.0;
        }
        marker_array.markers.push_back ( marker );

		/// status message
		pedsim_msgs::AgentState state;
        std_msgs::Header agent_header;
        agent_header.stamp = ros::Time::now();
        state.header = agent_header;

        state.id = a->getId();
        state.type = a->getType();
        state.position.x = a->getx();
        state.position.y = a->gety();
        state.position.z = a->getz();

        state.velocity.x = a->getvx();
        state.velocity.y = a->getvy();
        state.velocity.z = a->getvz();

        all_status.agent_states.push_back ( state );
    }

    // publish the marker array
    pub_agent_visuals_.publish ( marker_array );
	pub_all_agents_.publish ( all_status );
}

/// -----------------------------------------------------------------
/// \brief publishGroupVisuals
/// \details publish visualization of groups within the crowd
/// -----------------------------------------------------------------
void Simulator::publishGroupVisuals()
{
    QList<AgentGroup*> groups = SCENE.getGroups();

    /// visualize groups (sketchy)
    BOOST_FOREACH ( AgentGroup* ag, groups )
    {
        // skip empty ones
        if ( ag->memberCount() < 1)
         continue;

        // ag->updateCenterOfMass();
        Ped::Tvector gcom = ag->getCenterOfMass();

        // center
        visualization_msgs::Marker center_marker;
        center_marker.header.frame_id = "world";
        center_marker.header.stamp = ros::Time();
        center_marker.ns = "pedsim";
        center_marker.id = ag->getId();

        center_marker.color.a = 0.7;
        center_marker.color.r = 0.0;
        center_marker.color.g = 0.0;
        center_marker.color.b = 1.0;

        center_marker.scale.x = 0.2;
        center_marker.scale.y = 0.2;
        center_marker.scale.z = 0.2;

        center_marker.pose.position.x = gcom.x;
        center_marker.pose.position.y = gcom.y;
        center_marker.pose.position.z = center_marker.scale.z / 2.0;

        center_marker.pose.orientation.x = 0;
        center_marker.pose.orientation.y = 0;
        center_marker.pose.orientation.z = 0;
        center_marker.pose.orientation.w = 1;

        center_marker.type = visualization_msgs::Marker::CYLINDER;

        pub_group_centers_.publish ( center_marker );

        // members
        geometry_msgs::Point p1;
        p1.x = gcom.x;
        p1.y = gcom.y;
        p1.z = 0.0;

        BOOST_FOREACH ( Agent* m, ag->getMembers() )
        {
            visualization_msgs::Marker marker;
            marker.header.frame_id = "world";
            marker.header.stamp = ros::Time();
            marker.ns = "pedsim";
            marker.id = m->getId()+1000;

            marker.color.a = 0.7;
            marker.color.r = 0.0;
            marker.color.g = 0.0;
            marker.color.b = 1.0;

            marker.scale.x = 0.1;
            marker.scale.y = 0.2;
            marker.scale.z = 0.2;

            marker.type = visualization_msgs::Marker::ARROW;

            geometry_msgs::Point p2;
            p2.x = m->getx();
            p2.y = m->gety();
            p2.z = 0.0;

            marker.points.push_back ( p1 );
            marker.points.push_back ( p2 );

            pub_group_lines_.publish ( marker );
        }
    }
}

/// -----------------------------------------------------------------
/// \brief publishObstacles
/// \details publish obstacle cells with information about their
/// positions and cell sizes. Useful for path planning.
/// -----------------------------------------------------------------
void Simulator::publishObstacles()
{
    nav_msgs::GridCells obstacles;
    obstacles.header.frame_id = "world";
    obstacles.cell_width = 1.0;
    obstacles.cell_height = 1.0;

    std::vector<Location>::const_iterator it = SCENE.obstacle_cells_.begin();
    while ( it != SCENE.obstacle_cells_.end() )
    {
        geometry_msgs::Point p;
        Location loc = ( *it );
        // p.x = loc.x + (cell_size/2.0f);
        // p.y = loc.y + (cell_size/2.0f);
        p.x = loc.x;
        p.y = loc.y;
        p.z = 0.0;
        obstacles.cells.push_back ( p );

        it++;
    }

    pub_obstacles_.publish ( obstacles );
}

/// -----------------------------------------------------------------
/// \brief publishWalls
/// \details publish visual markers for obstacle given as 3D cells
/// for visualizing in rviz. Useful for visual plan inspection
/// -----------------------------------------------------------------
void Simulator::publishWalls()
{
    visualization_msgs::Marker marker;
    marker.header.frame_id = "world";
    marker.header.stamp = ros::Time();
    marker.ns = "pedsim";
    marker.id = 10000;

    marker.color.a = 1.0;
    marker.color.r = 1.0;
    marker.color.g = 0.0;
    marker.color.b = 0.0;

    marker.scale.x = 1.0;
    marker.scale.y = 1.0;
    marker.scale.z = 3.0;

    marker.pose.position.z = marker.scale.z / 2.0;

    marker.type = visualization_msgs::Marker::CUBE_LIST;

    std::vector<Location>::const_iterator it = SCENE.obstacle_cells_.begin();
    while ( it != SCENE.obstacle_cells_.end() )
    {
        geometry_msgs::Point p;
        Location loc = ( *it );
        p.x = loc.x;
        p.y = loc.y;
        p.z = 0.0;
        marker.points.push_back ( p );

        it++;
    }

    pub_walls_.publish ( marker );
}

/// -----------------------------------------------------------------
/// \brief publishAttractions
/// \details publish visual markers for attractions given as 3D cells
/// for visualizing in rviz.
/// -----------------------------------------------------------------
void Simulator::publishAttractions()
{
	QMap<QString, AttractionArea*>::iterator it = SCENE.getAttractions().begin();

	while ( it !=  SCENE.getAttractions().end() )

// 	QString s;
// 	AttractionArea* atr;

// 	BOOST_FOREACH( std::tie(s, atr), SCENE.getAttractions() )
	{
		AttractionArea* atr = it.value();

		ROS_INFO("Got value");

		visualization_msgs::Marker marker;
		marker.header.frame_id = "world";
		marker.header.stamp = ros::Time();
		marker.ns = "pedsim";
		marker.id = 20000;

		marker.color.a = 1.0;
		marker.color.r = 0.0;
		marker.color.g = 1.0;
		marker.color.b = 0.0;

		marker.scale.x = 1.0;
		marker.scale.y = 1.0;
		marker.scale.z = 3.0;

		marker.pose.position.x = atr->getPosition().x;
		marker.pose.position.y = atr->getPosition().y;
		marker.pose.position.z = marker.scale.z / 2.0;

		marker.type = visualization_msgs::Marker::CUBE;

		pub_attractions_.publish( marker );

		it++;
	}
}

/// -----------------------------------------------------------------
/// \brief main
/// Hub of the application
/// -----------------------------------------------------------------
int main ( int argc, char **argv )
{

	QApplication app(argc, argv);

    // initialize resources
    ros::init ( argc, argv, "simulator" );

    ROS_INFO ( "node initialized" );

    ros::NodeHandle node;

	Simulator sm(node);

	if ( sm.initializeSimulation() )
	{
		sm.runSimulation();
	}
	else
	{
		return EXIT_FAILURE;
	}

//     double x1, x2, y1, y2;
//     ros::param::param<double> ( "/pedsim/x1", x1, 0.0 );
//     ros::param::param<double> ( "/pedsim/x2", x2, 100.0 );
//     ros::param::param<double> ( "/pedsim/y1", y1, 0.0 );
//     ros::param::param<double> ( "/pedsim/y2", y2, 100.0 );
//
//     // Scene sim_scene(0, 0, 45, 45, node);
//     // Scene sim_scene(0, 0, 300, 100, node);
//     Scene sim_scene ( x1, y1, x2, y2, node );

	return app.exec();
}
<commit_msg>fixed attraction visualization bug<commit_after>

#include <pedsim_simulator/scene.h>

#include <pedsim_simulator/simulator.h>

#include <pedsim_simulator/element/agentcluster.h>

#include <QApplication>

Simulator::Simulator(const ros::NodeHandle &node)
	: nh_(node)
{
	// nothing to do here
}

Simulator::~Simulator()
{

}

bool Simulator::initializeSimulation()
{
	/// setup ros publishers
	pub_agent_visuals_ = nh_.advertise<visualization_msgs::MarkerArray> ( "agents_markers", 0 );
    pub_group_centers_ = nh_.advertise<visualization_msgs::Marker> ( "group_centers", 0 );
    pub_group_lines_ = nh_.advertise<visualization_msgs::Marker> ( "group_lines", 0 );
    pub_obstacles_ = nh_.advertise<nav_msgs::GridCells> ( "static_obstacles", 0 );
    pub_walls_ = nh_.advertise<visualization_msgs::Marker> ( "walls", 0 );
	pub_all_agents_ = nh_.advertise<pedsim_msgs::AllAgentsState> ( "dynamic_obstacles", 0 );
	pub_attractions_ = nh_.advertise<visualization_msgs::Marker> ( "attractions", 0 );
	pub_queues_ = nh_.advertise<visualization_msgs::Marker> ( "queues", 0 );

	/// setup any pointers
	orientation_handler_.reset ( new OrientationHandler() );

	/// subscribers
    sub_robot_command_ = nh_.subscribe ( "robot_state", 1, &Simulator::callbackRobotCommand, this );

	/// load parameters
    std::string scene_file_param;
    ros::param::param<std::string> ( "/simulator/scene_file", scene_file_param, "scene.xml" );
    // load scenario file
	// TODO - convert qstrings to std::strings
    QString scenefile = QString::fromStdString ( scene_file_param );

	ScenarioReader scenarioReader;
	bool readResult = scenarioReader.readFromFile(scenefile);
	if(readResult == false) {
		ROS_WARN ( "Could not load the scene file, check paths" );
		return false;
	}

    ROS_INFO ( "Loading from %s scene file", scene_file_param.c_str() );

	robot_ = nullptr;

	return true;
}

void Simulator::runSimulation()
{
	// setup the robot
    BOOST_FOREACH ( Agent* a, SCENE.getAgents() )
    {
		// TODO - convert back to robot type enum
        if ( a->getType() == 2 )
            robot_ = a;
    }

    ros::Rate r ( 30 ); // Hz

    while ( ros::ok() )
    {
		SCENE.moveAllAgents();

		publishAgentVisuals();

        publishGroupVisuals();

        // visuals for walls
        publishWalls();

        // only publish the obstacles in the beginning
        if ( SCENE.getTime() < 100 )
		{
            publishObstacles();
			publishAttractions();
		}

        ros::spinOnce();

        r.sleep();
    }
}

/// -----------------------------------------------------------------
/// \brief callbackRobotCommand
/// \details Control the robot based on the set velocity command
/// Listens to incoming messages and manipulates the robot.
/// \param[in] msg Message containing the pos and vel for the robot
/// -----------------------------------------------------------------
void Simulator::callbackRobotCommand ( const pedsim_msgs::AgentState::ConstPtr &msg )
{
    double vx = msg->velocity.x;
    double vy = msg->velocity.y;

//     if ( CONFIG.robot_mode == TELEOPERATION )
//         robot_->setteleop ( true );

    if ( robot_->getType() == msg->type )
    {
        if ( robot_->getTeleop() == false )
        {
            robot_->setvx ( vx );
            robot_->setvy ( vy );
            robot_->setVmax ( sqrt ( vx * vx + vy * vy ) );
        }
        else
        {
            robot_->setvx ( vx );
            robot_->setvy ( vy );
            robot_->setVmax ( sqrt ( vx * vx + vy * vy ) );
        }
    }
}

/// -----------------------------------------------------------------
/// \brief publishAgentVisuals
/// \details publish agent status information and the visual markers
/// -----------------------------------------------------------------
void Simulator::publishAgentVisuals()
{
    // minor optimization with arrays for speedup
    visualization_msgs::MarkerArray marker_array;

	// status message
	pedsim_msgs::AllAgentsState all_status;
    std_msgs::Header all_header;
    all_header.stamp = ros::Time::now();
    all_status.header = all_header;

    BOOST_FOREACH ( Agent* a, SCENE.getAgents() )
    {
		/// visual marker message
        visualization_msgs::Marker marker;
        marker.header.frame_id = "world";
        marker.header.stamp = ros::Time();
        marker.ns = "pedsim";
        marker.id = a->getId();

        marker.type = visualization_msgs::Marker::CYLINDER;
// 		marker.type = visualization_msgs::Marker::MESH_RESOURCE;
//         marker.mesh_resource = "package://pedsim_simulator/images/zoey/girl.dae";

		marker.action = 0;  // add or modify

		marker.scale.x = 0.3 / 2.0;
        marker.scale.y = 0.3;
        marker.scale.z = 1.75;

        marker.color.a = 1.0;
        marker.color.r = 0.0;
        marker.color.g = 0.7;
        marker.color.b = 1.0;

        marker.pose.position.z = marker.scale.z / 2.0;
        marker.pose.position.x = a->getx();
        marker.pose.position.y = a->gety();

        if ( a->getStateMachine()->getCurrentState() == AgentStateMachine::AgentState::StateQueueing)
        {
            marker.color.a = 1.0;
            marker.color.r = 1.0;
            marker.color.g = 0.0;
            marker.color.b = 1.0;
        }

        if ( a->getvx() != 0.0 )
        {
            // construct the orientation quaternion
            double theta = atan2 ( a->getvy(), a->getvx() );
            Eigen::Quaternionf q = orientation_handler_->angle2Quaternion ( theta
                                                                          );
            marker.pose.orientation.x = q.x();
            marker.pose.orientation.y = q.y();
            marker.pose.orientation.z = q.z();
            marker.pose.orientation.w = q.w();
        }
        else
        {
            marker.pose.orientation.x = 0.0;
            marker.pose.orientation.y = 0.0;
            marker.pose.orientation.z = 0.0;
            marker.pose.orientation.w = 1.0;
        }
        marker_array.markers.push_back ( marker );

		/// status message
		pedsim_msgs::AgentState state;
        std_msgs::Header agent_header;
        agent_header.stamp = ros::Time::now();
        state.header = agent_header;

        state.id = a->getId();
        state.type = a->getType();
        state.position.x = a->getx();
        state.position.y = a->gety();
        state.position.z = a->getz();

        state.velocity.x = a->getvx();
        state.velocity.y = a->getvy();
        state.velocity.z = a->getvz();

        all_status.agent_states.push_back ( state );
    }

    // publish the marker array
    pub_agent_visuals_.publish ( marker_array );
	pub_all_agents_.publish ( all_status );
}

/// -----------------------------------------------------------------
/// \brief publishGroupVisuals
/// \details publish visualization of groups within the crowd
/// -----------------------------------------------------------------
void Simulator::publishGroupVisuals()
{
    QList<AgentGroup*> groups = SCENE.getGroups();

    /// visualize groups (sketchy)
    BOOST_FOREACH ( AgentGroup* ag, groups )
    {
        // skip empty ones
        if ( ag->memberCount() < 1)
         continue;

        // ag->updateCenterOfMass();
        Ped::Tvector gcom = ag->getCenterOfMass();

        // center
        visualization_msgs::Marker center_marker;
        center_marker.header.frame_id = "world";
        center_marker.header.stamp = ros::Time();
        center_marker.ns = "pedsim";
        center_marker.id = ag->getId();

        center_marker.color.a = 0.7;
        center_marker.color.r = 0.0;
        center_marker.color.g = 0.0;
        center_marker.color.b = 1.0;

        center_marker.scale.x = 0.2;
        center_marker.scale.y = 0.2;
        center_marker.scale.z = 0.2;

        center_marker.pose.position.x = gcom.x;
        center_marker.pose.position.y = gcom.y;
        center_marker.pose.position.z = center_marker.scale.z / 2.0;

        center_marker.pose.orientation.x = 0;
        center_marker.pose.orientation.y = 0;
        center_marker.pose.orientation.z = 0;
        center_marker.pose.orientation.w = 1;

        center_marker.type = visualization_msgs::Marker::CYLINDER;

        pub_group_centers_.publish ( center_marker );

        // members
        geometry_msgs::Point p1;
        p1.x = gcom.x;
        p1.y = gcom.y;
        p1.z = 0.0;

        BOOST_FOREACH ( Agent* m, ag->getMembers() )
        {
            visualization_msgs::Marker marker;
            marker.header.frame_id = "world";
            marker.header.stamp = ros::Time();
            marker.ns = "pedsim";
            marker.id = m->getId()+1000;

            marker.color.a = 0.7;
            marker.color.r = 0.0;
            marker.color.g = 0.0;
            marker.color.b = 1.0;

            marker.scale.x = 0.1;
            marker.scale.y = 0.2;
            marker.scale.z = 0.2;

            marker.type = visualization_msgs::Marker::ARROW;

            geometry_msgs::Point p2;
            p2.x = m->getx();
            p2.y = m->gety();
            p2.z = 0.0;

            marker.points.push_back ( p1 );
            marker.points.push_back ( p2 );

            pub_group_lines_.publish ( marker );
        }
    }
}

/// -----------------------------------------------------------------
/// \brief publishObstacles
/// \details publish obstacle cells with information about their
/// positions and cell sizes. Useful for path planning.
/// -----------------------------------------------------------------
void Simulator::publishObstacles()
{
    nav_msgs::GridCells obstacles;
    obstacles.header.frame_id = "world";
    obstacles.cell_width = 1.0;
    obstacles.cell_height = 1.0;

    std::vector<Location>::const_iterator it = SCENE.obstacle_cells_.begin();
    while ( it != SCENE.obstacle_cells_.end() )
    {
        geometry_msgs::Point p;
        Location loc = ( *it );
        // p.x = loc.x + (cell_size/2.0f);
        // p.y = loc.y + (cell_size/2.0f);
        p.x = loc.x;
        p.y = loc.y;
        p.z = 0.0;
        obstacles.cells.push_back ( p );

        it++;
    }

    pub_obstacles_.publish ( obstacles );
}

/// -----------------------------------------------------------------
/// \brief publishWalls
/// \details publish visual markers for obstacle given as 3D cells
/// for visualizing in rviz. Useful for visual plan inspection
/// -----------------------------------------------------------------
void Simulator::publishWalls()
{
    visualization_msgs::Marker marker;
    marker.header.frame_id = "world";
    marker.header.stamp = ros::Time();
    marker.ns = "pedsim";
    marker.id = 10000;

    marker.color.a = 1.0;
    marker.color.r = 1.0;
    marker.color.g = 0.0;
    marker.color.b = 0.0;

    marker.scale.x = 1.0;
    marker.scale.y = 1.0;
    marker.scale.z = 3.0;

    marker.pose.position.z = marker.scale.z / 2.0;

    marker.type = visualization_msgs::Marker::CUBE_LIST;

    std::vector<Location>::const_iterator it = SCENE.obstacle_cells_.begin();
    while ( it != SCENE.obstacle_cells_.end() )
    {
        geometry_msgs::Point p;
        Location loc = ( *it );
        p.x = loc.x;
        p.y = loc.y;
        p.z = 0.0;
        marker.points.push_back ( p );

        it++;
    }

    pub_walls_.publish ( marker );
}

/// -----------------------------------------------------------------
/// \brief publishAttractions
/// \details publish visual markers for attractions given as 3D cells
/// for visualizing in rviz.
/// -----------------------------------------------------------------
void Simulator::publishAttractions()
{
	foreach( AttractionArea* atr, SCENE.getAttractions() )
	{

		visualization_msgs::Marker marker;
		marker.header.frame_id = "world";
		marker.header.stamp = ros::Time();
		marker.ns = "pedsim";
		marker.id = 20000;

		marker.color.a = 1.0;
		marker.color.r = 0.0;
		marker.color.g = 1.0;
		marker.color.b = 0.0;

		marker.scale.x = atr->getSize().width();
		marker.scale.y = atr->getSize().height();
		marker.scale.z = 3.0;

		marker.pose.position.x = atr->getPosition().x;
		marker.pose.position.y = atr->getPosition().y;
		marker.pose.position.z = marker.scale.z / 2.0;

		marker.type = visualization_msgs::Marker::CUBE;

		pub_attractions_.publish( marker );
	}
}

/// -----------------------------------------------------------------
/// \brief main
/// Hub of the application
/// -----------------------------------------------------------------
int main ( int argc, char **argv )
{

	QApplication app(argc, argv);

    // initialize resources
    ros::init ( argc, argv, "simulator" );

    ROS_INFO ( "node initialized" );

    ros::NodeHandle node;

	Simulator sm(node);

	if ( sm.initializeSimulation() )
	{
		sm.runSimulation();
	}
	else
	{
		return EXIT_FAILURE;
	}

//     double x1, x2, y1, y2;
//     ros::param::param<double> ( "/pedsim/x1", x1, 0.0 );
//     ros::param::param<double> ( "/pedsim/x2", x2, 100.0 );
//     ros::param::param<double> ( "/pedsim/y1", y1, 0.0 );
//     ros::param::param<double> ( "/pedsim/y2", y2, 100.0 );
//
//     // Scene sim_scene(0, 0, 45, 45, node);
//     // Scene sim_scene(0, 0, 300, 100, node);
//     Scene sim_scene ( x1, y1, x2, y2, node );

	return app.exec();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <wangle/ssl/SSLSessionCacheManager.h>

#include <wangle/ssl/SSLCacheProvider.h>
#include <wangle/ssl/SSLStats.h>
#include <wangle/ssl/SSLUtil.h>

#include <folly/fibers/Fiber.h>
#include <folly/fibers/FiberManager.h>
#include <folly/io/async/EventBase.h>
#include <folly/portability/GFlags.h>
#include <folly/portability/OpenSSL.h>

using folly::AsyncSSLSocket;
using folly::SSLContext;
using std::shared_ptr;
using std::string;

namespace {

const uint32_t NUM_CACHE_BUCKETS = 16;

// We use the default ID generator which fills the maximum ID length
// for the protocol.  16 bytes for SSLv2 or 32 for SSLv3+
const int MIN_SESSION_ID_LENGTH = 16;

} // namespace

FOLLY_GFLAGS_DEFINE_bool(
    dcache_unit_test,
    false,
    "All VIPs share one session cache");

namespace wangle {

int SSLSessionCacheManager::sExDataIndex_ = -1;
shared_ptr<ShardedLocalSSLSessionCache> SSLSessionCacheManager::sCache_;
std::mutex SSLSessionCacheManager::sCacheLock_;

LocalSSLSessionCache::LocalSSLSessionCache(
    uint32_t maxCacheSize,
    uint32_t cacheCullSize)
    : sessionCache(maxCacheSize, cacheCullSize) {
  sessionCache.setPruneHook(std::bind(
      &LocalSSLSessionCache::pruneSessionCallback,
      this,
      std::placeholders::_1,
      std::placeholders::_2));
}

void LocalSSLSessionCache::pruneSessionCallback(
    const string& sessionId,
    SSL_SESSION* session) {
  VLOG(4) << "Free SSL session from local cache; id="
          << SSLUtil::hexlify(sessionId);
  SSL_SESSION_free(session);
  ++removedSessions_;
}

// ShardedLocalSSLSessionCache Implementation
ShardedLocalSSLSessionCache::ShardedLocalSSLSessionCache(
    uint32_t n_buckets,
    uint32_t maxCacheSize,
    uint32_t cacheCullSize) {
  CHECK(n_buckets > 0);
  maxCacheSize = (uint32_t)(((double)maxCacheSize) / n_buckets);
  cacheCullSize = (uint32_t)(((double)cacheCullSize) / n_buckets);
  if (maxCacheSize == 0) {
    maxCacheSize = 1;
  }
  if (cacheCullSize == 0) {
    cacheCullSize = 1;
  }
  for (uint32_t i = 0; i < n_buckets; i++) {
    caches_.push_back(std::unique_ptr<LocalSSLSessionCache>(
        new LocalSSLSessionCache(maxCacheSize, cacheCullSize)));
  }
}

SSL_SESSION* ShardedLocalSSLSessionCache::lookupSession(
    const std::string& sessionId) {
  size_t bucket = hash(sessionId);
  SSL_SESSION* session = nullptr;
  std::lock_guard<std::mutex> g(caches_[bucket]->lock);

  auto itr = caches_[bucket]->sessionCache.find(sessionId);
  if (itr != caches_[bucket]->sessionCache.end()) {
    session = itr->second;
  }

  if (session) {
    SSL_SESSION_up_ref(session);
  }
  return session;
}

void ShardedLocalSSLSessionCache::storeSession(
    const std::string& sessionId,
    SSL_SESSION* session,
    SSLStats* stats) {
  size_t bucket = hash(sessionId);
  SSL_SESSION* oldSession = nullptr;
  std::lock_guard<std::mutex> g(caches_[bucket]->lock);

  auto itr = caches_[bucket]->sessionCache.find(sessionId);
  if (itr != caches_[bucket]->sessionCache.end()) {
    oldSession = itr->second;
  }

  if (oldSession) {
    // LRUCacheMap doesn't free on overwrite, so 2x the work for us
    // This can happen in race conditions
    SSL_SESSION_free(oldSession);
  }
  caches_[bucket]->removedSessions_ = 0;
  caches_[bucket]->sessionCache.set(sessionId, session, true);
  if (stats) {
    stats->recordSSLSessionFree(caches_[bucket]->removedSessions_);
  }
}

void ShardedLocalSSLSessionCache::removeSession(const std::string& sessionId) {
  size_t bucket = hash(sessionId);
  std::lock_guard<std::mutex> g(caches_[bucket]->lock);

  auto itr = caches_[bucket]->sessionCache.find(sessionId);
  if (itr == caches_[bucket]->sessionCache.end()) {
    VLOG(4) << "session ID " << sessionId << " not in cache";
    return;
  }

  // LRUCacheMap doesn't free on erase either
  SSL_SESSION_free(itr->second);
  caches_[bucket]->sessionCache.erase(sessionId);
}

// SSLSessionCacheManager implementation

SSLSessionCacheManager::SSLSessionCacheManager(
    uint32_t maxCacheSize,
    uint32_t cacheCullSize,
    SSLContext* ctx,
    const string& context,
    SSLStats* stats,
    const std::shared_ptr<SSLCacheProvider>& externalCache)
    : ctx_(ctx), stats_(stats), externalCache_(externalCache) {
  SSL_CTX* sslCtx = ctx->getSSLCtx();

  SSLUtil::getSSLCtxExIndex(&sExDataIndex_);

  SSL_CTX_set_ex_data(sslCtx, sExDataIndex_, this);
  SSL_CTX_sess_set_get_cb(sslCtx, SSLSessionCacheManager::getSessionCallback);
  SSL_CTX_sess_set_remove_cb(
      sslCtx, SSLSessionCacheManager::removeSessionCallback);
  ctx->setSessionLifecycleCallbacks(
      std::make_unique<ContextSessionCallbacks>());
  if (!FLAGS_dcache_unit_test && !context.empty()) {
    // Use the passed in context
    ctx->setSessionCacheContext(context);
  }

  SSL_CTX_set_session_cache_mode(
      sslCtx, SSL_SESS_CACHE_NO_INTERNAL | SSL_SESS_CACHE_SERVER);

  localCache_ =
      SSLSessionCacheManager::getLocalCache(maxCacheSize, cacheCullSize);
}

SSLSessionCacheManager::~SSLSessionCacheManager() {}

void SSLSessionCacheManager::shutdown() {
  std::lock_guard<std::mutex> g(sCacheLock_);
  sCache_.reset();
}

shared_ptr<ShardedLocalSSLSessionCache> SSLSessionCacheManager::getLocalCache(
    uint32_t maxCacheSize,
    uint32_t cacheCullSize) {
  std::lock_guard<std::mutex> g(sCacheLock_);
  if (!sCache_) {
    sCache_.reset(new ShardedLocalSSLSessionCache(
        NUM_CACHE_BUCKETS, maxCacheSize, cacheCullSize));
  }
  return sCache_;
}

void SSLSessionCacheManager::newSession(SSL*, SSL_SESSION* session) {
  unsigned int sessIdLen = 0;
  const unsigned char* sessId = SSL_SESSION_get_id(session, &sessIdLen);
  string sessionId((char*)sessId, sessIdLen);
  VLOG(4) << "New SSL session; id=" << SSLUtil::hexlify(sessionId);

  if (stats_) {
    stats_->recordSSLSession(true /* new session */, false, false);
  }

  localCache_->storeSession(sessionId, session, stats_);

  if (externalCache_) {
    VLOG(4) << "New SSL session: send session to external cache; id="
            << SSLUtil::hexlify(sessionId);
    storeCacheRecord(sessionId, session);
  }
}

void SSLSessionCacheManager::removeSessionCallback(
    SSL_CTX* ctx,
    SSL_SESSION* session) {
  SSLSessionCacheManager* manager = nullptr;
  manager = (SSLSessionCacheManager*)SSL_CTX_get_ex_data(ctx, sExDataIndex_);

  if (manager == nullptr) {
    LOG(FATAL) << "Null SSLSessionCacheManager in callback";
  }
  return manager->removeSession(ctx, session);
}

void SSLSessionCacheManager::removeSession(SSL_CTX*, SSL_SESSION* session) {
  unsigned int sessIdLen = 0;
  const unsigned char* sessId = SSL_SESSION_get_id(session, &sessIdLen);
  string sessionId((char*)sessId, sessIdLen);

  // This hook is only called from SSL when the internal session cache needs to
  // flush sessions.  Since we run with the internal cache disabled, this should
  // never be called
  VLOG(3) << "Remove SSL session; id=" << SSLUtil::hexlify(sessionId);

  localCache_->removeSession(sessionId);

  if (stats_) {
    stats_->recordSSLSessionRemove();
  }
}

SSL_SESSION* SSLSessionCacheManager::getSessionCallback(
    SSL* ssl,
    session_callback_arg_session_id_t sess_id,
    int id_len,
    int* copyflag) {
  SSLSessionCacheManager* manager = nullptr;
  SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
  manager = (SSLSessionCacheManager*)SSL_CTX_get_ex_data(ctx, sExDataIndex_);

  if (manager == nullptr) {
    LOG(FATAL) << "Null SSLSessionCacheManager in callback";
  }
  return manager->getSession(ssl, (unsigned char*)sess_id, id_len, copyflag);
}

SSL_SESSION* SSLSessionCacheManager::getSession(
    SSL* ssl,
    unsigned char* session_id,
    int id_len,
    int* copyflag) {
  VLOG(7) << "SSL get session callback";
  folly::ssl::SSLSessionUniquePtr session;
  bool foreign = false;
  std::string missReason;

  if (id_len < MIN_SESSION_ID_LENGTH) {
    // We didn't generate this session so it's going to be a miss.
    // This doesn't get logged or counted in the stats.
    return nullptr;
  }
  string sessionId((char*)session_id, id_len);

  AsyncSSLSocket* sslSocket = AsyncSSLSocket::getFromSSL(ssl);

  assert(sslSocket != nullptr);

  // look it up in the local cache first
  session.reset(localCache_->lookupSession(sessionId));
#if FOLLY_OPENSSL_IS_110
  if (session == nullptr && externalCache_) {
    foreign = true;
    DCHECK(folly::fibers::onFiber());
    if (folly::fibers::onFiber()) {
      try {
        session = externalCache_->getFuture(sessionId).get();
      } catch (const std::exception& e) {
        missReason = folly::to<std::string>("reason: ", e.what(), ";");
      }

      if (session) {
        SSL_SESSION_up_ref(session.get());
        localCache_->storeSession(sessionId, session.get(), stats_);
      }
    } else {
      missReason = "reason: request not running on fiber;";
    }
  }
#endif

  bool hit = (session != nullptr);
  if (stats_) {
    stats_->recordSSLSession(false, hit, foreign);
  }
  if (hit) {
    sslSocket->setSessionIDResumed(true);
  }

  VLOG(4) << "Get SSL session [" << ((hit) ? "Hit" : "Miss")
          << "]: " << ((foreign) ? "external" : "local") << " cache; "
          << missReason << "fd=" << sslSocket->getNetworkSocket().toFd()
          << " id=" << SSLUtil::hexlify(sessionId);

  // We already bumped the refcount
  *copyflag = 0;

  return session.release();
}

bool SSLSessionCacheManager::storeCacheRecord(
    const string& sessionId,
    SSL_SESSION* session) {
  std::string sessionString;
  uint32_t sessionLen = i2d_SSL_SESSION(session, nullptr);
  sessionString.resize(sessionLen);
  uint8_t* cp = (uint8_t*)sessionString.data();
  i2d_SSL_SESSION(session, &cp);
  size_t expiration = SSL_CTX_get_timeout(ctx_->getSSLCtx());
  return externalCache_->setAsync(
      sessionId, sessionString, std::chrono::seconds(expiration));
}

void SSLSessionCacheManager::ContextSessionCallbacks::onNewSession(
    SSL* ssl,
    folly::ssl::SSLSessionUniquePtr sessionPtr) {
  SSLSessionCacheManager* manager = nullptr;
  SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
  manager = (SSLSessionCacheManager*)SSL_CTX_get_ex_data(ctx, sExDataIndex_);

  CHECK(manager) << "Null SSLSessionCacheManager in callback";
  manager->newSession(ssl, sessionPtr.release());
}

} // namespace wangle
<commit_msg>Revert D38066654: revise gflags portability<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <wangle/ssl/SSLSessionCacheManager.h>

#include <wangle/ssl/SSLCacheProvider.h>
#include <wangle/ssl/SSLStats.h>
#include <wangle/ssl/SSLUtil.h>

#include <folly/fibers/Fiber.h>
#include <folly/fibers/FiberManager.h>
#include <folly/io/async/EventBase.h>
#include <folly/portability/GFlags.h>
#include <folly/portability/OpenSSL.h>

using folly::AsyncSSLSocket;
using folly::SSLContext;
using std::shared_ptr;
using std::string;

namespace {

const uint32_t NUM_CACHE_BUCKETS = 16;

// We use the default ID generator which fills the maximum ID length
// for the protocol.  16 bytes for SSLv2 or 32 for SSLv3+
const int MIN_SESSION_ID_LENGTH = 16;

} // namespace

DEFINE_bool(dcache_unit_test, false, "All VIPs share one session cache");

namespace wangle {

int SSLSessionCacheManager::sExDataIndex_ = -1;
shared_ptr<ShardedLocalSSLSessionCache> SSLSessionCacheManager::sCache_;
std::mutex SSLSessionCacheManager::sCacheLock_;

LocalSSLSessionCache::LocalSSLSessionCache(
    uint32_t maxCacheSize,
    uint32_t cacheCullSize)
    : sessionCache(maxCacheSize, cacheCullSize) {
  sessionCache.setPruneHook(std::bind(
      &LocalSSLSessionCache::pruneSessionCallback,
      this,
      std::placeholders::_1,
      std::placeholders::_2));
}

void LocalSSLSessionCache::pruneSessionCallback(
    const string& sessionId,
    SSL_SESSION* session) {
  VLOG(4) << "Free SSL session from local cache; id="
          << SSLUtil::hexlify(sessionId);
  SSL_SESSION_free(session);
  ++removedSessions_;
}

// ShardedLocalSSLSessionCache Implementation
ShardedLocalSSLSessionCache::ShardedLocalSSLSessionCache(
    uint32_t n_buckets,
    uint32_t maxCacheSize,
    uint32_t cacheCullSize) {
  CHECK(n_buckets > 0);
  maxCacheSize = (uint32_t)(((double)maxCacheSize) / n_buckets);
  cacheCullSize = (uint32_t)(((double)cacheCullSize) / n_buckets);
  if (maxCacheSize == 0) {
    maxCacheSize = 1;
  }
  if (cacheCullSize == 0) {
    cacheCullSize = 1;
  }
  for (uint32_t i = 0; i < n_buckets; i++) {
    caches_.push_back(std::unique_ptr<LocalSSLSessionCache>(
        new LocalSSLSessionCache(maxCacheSize, cacheCullSize)));
  }
}

SSL_SESSION* ShardedLocalSSLSessionCache::lookupSession(
    const std::string& sessionId) {
  size_t bucket = hash(sessionId);
  SSL_SESSION* session = nullptr;
  std::lock_guard<std::mutex> g(caches_[bucket]->lock);

  auto itr = caches_[bucket]->sessionCache.find(sessionId);
  if (itr != caches_[bucket]->sessionCache.end()) {
    session = itr->second;
  }

  if (session) {
    SSL_SESSION_up_ref(session);
  }
  return session;
}

void ShardedLocalSSLSessionCache::storeSession(
    const std::string& sessionId,
    SSL_SESSION* session,
    SSLStats* stats) {
  size_t bucket = hash(sessionId);
  SSL_SESSION* oldSession = nullptr;
  std::lock_guard<std::mutex> g(caches_[bucket]->lock);

  auto itr = caches_[bucket]->sessionCache.find(sessionId);
  if (itr != caches_[bucket]->sessionCache.end()) {
    oldSession = itr->second;
  }

  if (oldSession) {
    // LRUCacheMap doesn't free on overwrite, so 2x the work for us
    // This can happen in race conditions
    SSL_SESSION_free(oldSession);
  }
  caches_[bucket]->removedSessions_ = 0;
  caches_[bucket]->sessionCache.set(sessionId, session, true);
  if (stats) {
    stats->recordSSLSessionFree(caches_[bucket]->removedSessions_);
  }
}

void ShardedLocalSSLSessionCache::removeSession(const std::string& sessionId) {
  size_t bucket = hash(sessionId);
  std::lock_guard<std::mutex> g(caches_[bucket]->lock);

  auto itr = caches_[bucket]->sessionCache.find(sessionId);
  if (itr == caches_[bucket]->sessionCache.end()) {
    VLOG(4) << "session ID " << sessionId << " not in cache";
    return;
  }

  // LRUCacheMap doesn't free on erase either
  SSL_SESSION_free(itr->second);
  caches_[bucket]->sessionCache.erase(sessionId);
}

// SSLSessionCacheManager implementation

SSLSessionCacheManager::SSLSessionCacheManager(
    uint32_t maxCacheSize,
    uint32_t cacheCullSize,
    SSLContext* ctx,
    const string& context,
    SSLStats* stats,
    const std::shared_ptr<SSLCacheProvider>& externalCache)
    : ctx_(ctx), stats_(stats), externalCache_(externalCache) {
  SSL_CTX* sslCtx = ctx->getSSLCtx();

  SSLUtil::getSSLCtxExIndex(&sExDataIndex_);

  SSL_CTX_set_ex_data(sslCtx, sExDataIndex_, this);
  SSL_CTX_sess_set_get_cb(sslCtx, SSLSessionCacheManager::getSessionCallback);
  SSL_CTX_sess_set_remove_cb(
      sslCtx, SSLSessionCacheManager::removeSessionCallback);
  ctx->setSessionLifecycleCallbacks(
      std::make_unique<ContextSessionCallbacks>());
  if (!FLAGS_dcache_unit_test && !context.empty()) {
    // Use the passed in context
    ctx->setSessionCacheContext(context);
  }

  SSL_CTX_set_session_cache_mode(
      sslCtx, SSL_SESS_CACHE_NO_INTERNAL | SSL_SESS_CACHE_SERVER);

  localCache_ =
      SSLSessionCacheManager::getLocalCache(maxCacheSize, cacheCullSize);
}

SSLSessionCacheManager::~SSLSessionCacheManager() {}

void SSLSessionCacheManager::shutdown() {
  std::lock_guard<std::mutex> g(sCacheLock_);
  sCache_.reset();
}

shared_ptr<ShardedLocalSSLSessionCache> SSLSessionCacheManager::getLocalCache(
    uint32_t maxCacheSize,
    uint32_t cacheCullSize) {
  std::lock_guard<std::mutex> g(sCacheLock_);
  if (!sCache_) {
    sCache_.reset(new ShardedLocalSSLSessionCache(
        NUM_CACHE_BUCKETS, maxCacheSize, cacheCullSize));
  }
  return sCache_;
}

void SSLSessionCacheManager::newSession(SSL*, SSL_SESSION* session) {
  unsigned int sessIdLen = 0;
  const unsigned char* sessId = SSL_SESSION_get_id(session, &sessIdLen);
  string sessionId((char*)sessId, sessIdLen);
  VLOG(4) << "New SSL session; id=" << SSLUtil::hexlify(sessionId);

  if (stats_) {
    stats_->recordSSLSession(true /* new session */, false, false);
  }

  localCache_->storeSession(sessionId, session, stats_);

  if (externalCache_) {
    VLOG(4) << "New SSL session: send session to external cache; id="
            << SSLUtil::hexlify(sessionId);
    storeCacheRecord(sessionId, session);
  }
}

void SSLSessionCacheManager::removeSessionCallback(
    SSL_CTX* ctx,
    SSL_SESSION* session) {
  SSLSessionCacheManager* manager = nullptr;
  manager = (SSLSessionCacheManager*)SSL_CTX_get_ex_data(ctx, sExDataIndex_);

  if (manager == nullptr) {
    LOG(FATAL) << "Null SSLSessionCacheManager in callback";
  }
  return manager->removeSession(ctx, session);
}

void SSLSessionCacheManager::removeSession(SSL_CTX*, SSL_SESSION* session) {
  unsigned int sessIdLen = 0;
  const unsigned char* sessId = SSL_SESSION_get_id(session, &sessIdLen);
  string sessionId((char*)sessId, sessIdLen);

  // This hook is only called from SSL when the internal session cache needs to
  // flush sessions.  Since we run with the internal cache disabled, this should
  // never be called
  VLOG(3) << "Remove SSL session; id=" << SSLUtil::hexlify(sessionId);

  localCache_->removeSession(sessionId);

  if (stats_) {
    stats_->recordSSLSessionRemove();
  }
}

SSL_SESSION* SSLSessionCacheManager::getSessionCallback(
    SSL* ssl,
    session_callback_arg_session_id_t sess_id,
    int id_len,
    int* copyflag) {
  SSLSessionCacheManager* manager = nullptr;
  SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
  manager = (SSLSessionCacheManager*)SSL_CTX_get_ex_data(ctx, sExDataIndex_);

  if (manager == nullptr) {
    LOG(FATAL) << "Null SSLSessionCacheManager in callback";
  }
  return manager->getSession(ssl, (unsigned char*)sess_id, id_len, copyflag);
}

SSL_SESSION* SSLSessionCacheManager::getSession(
    SSL* ssl,
    unsigned char* session_id,
    int id_len,
    int* copyflag) {
  VLOG(7) << "SSL get session callback";
  folly::ssl::SSLSessionUniquePtr session;
  bool foreign = false;
  std::string missReason;

  if (id_len < MIN_SESSION_ID_LENGTH) {
    // We didn't generate this session so it's going to be a miss.
    // This doesn't get logged or counted in the stats.
    return nullptr;
  }
  string sessionId((char*)session_id, id_len);

  AsyncSSLSocket* sslSocket = AsyncSSLSocket::getFromSSL(ssl);

  assert(sslSocket != nullptr);

  // look it up in the local cache first
  session.reset(localCache_->lookupSession(sessionId));
#if FOLLY_OPENSSL_IS_110
  if (session == nullptr && externalCache_) {
    foreign = true;
    DCHECK(folly::fibers::onFiber());
    if (folly::fibers::onFiber()) {
      try {
        session = externalCache_->getFuture(sessionId).get();
      } catch (const std::exception& e) {
        missReason = folly::to<std::string>("reason: ", e.what(), ";");
      }

      if (session) {
        SSL_SESSION_up_ref(session.get());
        localCache_->storeSession(sessionId, session.get(), stats_);
      }
    } else {
      missReason = "reason: request not running on fiber;";
    }
  }
#endif

  bool hit = (session != nullptr);
  if (stats_) {
    stats_->recordSSLSession(false, hit, foreign);
  }
  if (hit) {
    sslSocket->setSessionIDResumed(true);
  }

  VLOG(4) << "Get SSL session [" << ((hit) ? "Hit" : "Miss")
          << "]: " << ((foreign) ? "external" : "local") << " cache; "
          << missReason << "fd=" << sslSocket->getNetworkSocket().toFd()
          << " id=" << SSLUtil::hexlify(sessionId);

  // We already bumped the refcount
  *copyflag = 0;

  return session.release();
}

bool SSLSessionCacheManager::storeCacheRecord(
    const string& sessionId,
    SSL_SESSION* session) {
  std::string sessionString;
  uint32_t sessionLen = i2d_SSL_SESSION(session, nullptr);
  sessionString.resize(sessionLen);
  uint8_t* cp = (uint8_t*)sessionString.data();
  i2d_SSL_SESSION(session, &cp);
  size_t expiration = SSL_CTX_get_timeout(ctx_->getSSLCtx());
  return externalCache_->setAsync(
      sessionId, sessionString, std::chrono::seconds(expiration));
}

void SSLSessionCacheManager::ContextSessionCallbacks::onNewSession(
    SSL* ssl,
    folly::ssl::SSLSessionUniquePtr sessionPtr) {
  SSLSessionCacheManager* manager = nullptr;
  SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
  manager = (SSLSessionCacheManager*)SSL_CTX_get_ex_data(ctx, sExDataIndex_);

  CHECK(manager) << "Null SSLSessionCacheManager in callback";
  manager->newSession(ssl, sessionPtr.release());
}

} // namespace wangle
<|endoftext|>


<commit_before>#include "mock_server.h"

#include <cstring>
#include <sstream>

#include <Poco/Net/DatagramSocket.h>
#include <Poco/Net/ServerSocket.h>
#include <Poco/Net/StreamSocket.h>
#include <gtest/gtest.h>

MockServer::MockServer() : shutdown_{false}, continue_{false}, initialized_{false} {
  std::unique_lock<std::mutex> lock(mutex_);
  server_thread_ = std::thread(&MockServer::serverThread, this);

  cv_.wait(lock, [this] { return initialized_; });
}

MockServer::~MockServer() {
  {
    std::lock_guard<std::mutex> _(mutex_);
    shutdown_ = true;
  }
  cv_.notify_one();
  server_thread_.join();

  if (!commands_.empty()) {
    std::stringstream ss;
    ss << "Mock server did not process all commands. Unprocessed commands:" << std::endl;
    while (!commands_.empty()) {
      ss << commands_.front().first << std::endl;
      commands_.pop();
    }
    ADD_FAILURE() << ss.str();
  }
}

MockServer& MockServer::onConnect(ConnectCallbackT on_connect) {
  on_connect_ = on_connect;
  return *this;
}

MockServer& MockServer::onStartMotionGenerator(
    StartMotionGeneratorCallbackT on_start_motion_generator) {
  return waitForCommand<research_interface::StartMotionGenerator>(on_start_motion_generator);
}

MockServer& MockServer::onStopMotionGenerator(
    StopMotionGeneratorCallbackT on_stop_motion_generator) {
  return waitForCommand<research_interface::StopMotionGenerator>(on_stop_motion_generator);
}

MockServer& MockServer::onStartController(StartControllerCallbackT on_start_controller) {
  return waitForCommand<research_interface::StartController>(on_start_controller);
}

MockServer& MockServer::onStopController(StopControllerCallbackT on_stop_motion_generator) {
  return waitForCommand<research_interface::StopController>(on_stop_motion_generator);
}

MockServer& MockServer::sendEmptyRobotState() {
  return onSendRobotState(SendRobotStateAlternativeCallbackT());
}

MockServer& MockServer::onSendRobotState(SendRobotStateCallbackT on_send_robot_state) {
  std::lock_guard<std::mutex> _(mutex_);
  commands_.emplace("onSendRobotState", [=](Socket&, Socket& udp_socket) {
    research_interface::RobotState robot_state = on_send_robot_state();
    udp_socket.sendBytes(&robot_state, sizeof(robot_state));
  });
  return *this;
}

MockServer& MockServer::onSendRobotState(SendRobotStateAlternativeCallbackT on_send_robot_state) {
  return onSendRobotState([=]() {
    research_interface::RobotState robot_state;
    std::memset(&robot_state, 0, sizeof(robot_state));
    if (on_send_robot_state) {
      on_send_robot_state(robot_state);
    }
    return robot_state;
  });
}

MockServer& MockServer::onReceiveRobotCommand(
    ReceiveRobotCommandCallbackT on_receive_robot_command) {
  std::lock_guard<std::mutex> _(mutex_);
  commands_.emplace("onReceiveRobotCommand", [=](Socket&, Socket& udp_socket) {
    research_interface::RobotCommand robot_command;
    udp_socket.receiveBytes(&robot_command, sizeof(robot_command));
    on_receive_robot_command(robot_command);
  });
  return *this;
}

void MockServer::spinOnce(bool block) {
  std::unique_lock<std::mutex> lock(mutex_);
  continue_ = true;
  cv_.notify_one();
  if (block) {
    cv_.wait(lock, [this]() { return !continue_; });
  }
}

void MockServer::serverThread() {
  std::unique_lock<std::mutex> lock(mutex_);

  const std::string kHostname = "localhost";
  Poco::Net::ServerSocket srv;

  srv =
      Poco::Net::ServerSocket({kHostname, research_interface::kCommandPort});  // does bind + listen
  initialized_ = true;

  cv_.notify_one();
  cv_.wait(lock, [this] { return continue_; });

  Poco::Net::SocketAddress remote_address;
  Poco::Net::StreamSocket tcp_socket = srv.acceptConnection(remote_address);
  tcp_socket.setBlocking(true);
  tcp_socket.setNoDelay(true);

  Socket tcp_socket_wrapper;
  tcp_socket_wrapper.sendBytes = [&](const void* data, size_t size) {
    int rv = tcp_socket.sendBytes(data, size);
    ASSERT_EQ(static_cast<int>(size), rv);
  };
  tcp_socket_wrapper.receiveBytes = [&](void* data, size_t size) {
    int rv = tcp_socket.receiveBytes(data, size);
    ASSERT_EQ(static_cast<int>(size), rv);
  };

  uint16_t udp_port;
  handleCommand<research_interface::Connect>(
      tcp_socket_wrapper, [&, this](const research_interface::Connect::Request& request) {
        udp_port = request.udp_port;
        return on_connect_ ? on_connect_(request)
                           : research_interface::Connect::Response(
                                 research_interface::Connect::Status::kSuccess);
      });

  Poco::Net::DatagramSocket udp_socket({kHostname, 0});
  udp_socket.setBlocking(true);
  Socket udp_socket_wrapper;
  udp_socket_wrapper.sendBytes = [&](const void* data, size_t size) {
    int rv = udp_socket.sendTo(data, size, {remote_address.host(), udp_port});
    ASSERT_EQ(static_cast<int>(size), rv);
  };
  udp_socket_wrapper.receiveBytes = [&](void* data, size_t size) {
    int rv = udp_socket.receiveFrom(data, size, remote_address);
    ASSERT_EQ(static_cast<int>(size), rv);
  };

  while (!shutdown_) {
    cv_.wait(lock, [this] { return continue_ || shutdown_; });
    while (!commands_.empty()) {
      commands_.front().second(tcp_socket_wrapper, udp_socket_wrapper);
      commands_.pop();
    }

    ASSERT_FALSE(udp_socket.poll(Poco::Timespan(), Poco::Net::Socket::SelectMode::SELECT_READ));

    if (tcp_socket.poll(Poco::Timespan(), Poco::Net::Socket::SelectMode::SELECT_READ)) {
      // Received something on the TCP socket.
      // Test that the Robot closed the connection.
      std::array<uint8_t, 16> buffer;

      int rv = tcp_socket.receiveBytes(buffer.data(), buffer.size());
      ASSERT_EQ(0, rv);
    }

    continue_ = false;
    cv_.notify_one();
  }
}
<commit_msg>Tests: Add assert failure messages to MockServer.<commit_after>#include "mock_server.h"

#include <cstring>
#include <sstream>

#include <Poco/Net/DatagramSocket.h>
#include <Poco/Net/ServerSocket.h>
#include <Poco/Net/StreamSocket.h>
#include <gtest/gtest.h>

MockServer::MockServer() : shutdown_{false}, continue_{false}, initialized_{false} {
  std::unique_lock<std::mutex> lock(mutex_);
  server_thread_ = std::thread(&MockServer::serverThread, this);

  cv_.wait(lock, [this] { return initialized_; });
}

MockServer::~MockServer() {
  {
    std::lock_guard<std::mutex> _(mutex_);
    shutdown_ = true;
  }
  cv_.notify_one();
  server_thread_.join();

  if (!commands_.empty()) {
    std::stringstream ss;
    ss << "Mock server did not process all commands. Unprocessed commands:" << std::endl;
    while (!commands_.empty()) {
      ss << commands_.front().first << std::endl;
      commands_.pop();
    }
    ADD_FAILURE() << ss.str();
  }
}

MockServer& MockServer::onConnect(ConnectCallbackT on_connect) {
  on_connect_ = on_connect;
  return *this;
}

MockServer& MockServer::onStartMotionGenerator(
    StartMotionGeneratorCallbackT on_start_motion_generator) {
  return waitForCommand<research_interface::StartMotionGenerator>(on_start_motion_generator);
}

MockServer& MockServer::onStopMotionGenerator(
    StopMotionGeneratorCallbackT on_stop_motion_generator) {
  return waitForCommand<research_interface::StopMotionGenerator>(on_stop_motion_generator);
}

MockServer& MockServer::onStartController(StartControllerCallbackT on_start_controller) {
  return waitForCommand<research_interface::StartController>(on_start_controller);
}

MockServer& MockServer::onStopController(StopControllerCallbackT on_stop_motion_generator) {
  return waitForCommand<research_interface::StopController>(on_stop_motion_generator);
}

MockServer& MockServer::sendEmptyRobotState() {
  return onSendRobotState(SendRobotStateAlternativeCallbackT());
}

MockServer& MockServer::onSendRobotState(SendRobotStateCallbackT on_send_robot_state) {
  std::lock_guard<std::mutex> _(mutex_);
  commands_.emplace("onSendRobotState", [=](Socket&, Socket& udp_socket) {
    research_interface::RobotState robot_state = on_send_robot_state();
    udp_socket.sendBytes(&robot_state, sizeof(robot_state));
  });
  return *this;
}

MockServer& MockServer::onSendRobotState(SendRobotStateAlternativeCallbackT on_send_robot_state) {
  return onSendRobotState([=]() {
    research_interface::RobotState robot_state;
    std::memset(&robot_state, 0, sizeof(robot_state));
    if (on_send_robot_state) {
      on_send_robot_state(robot_state);
    }
    return robot_state;
  });
}

MockServer& MockServer::onReceiveRobotCommand(
    ReceiveRobotCommandCallbackT on_receive_robot_command) {
  std::lock_guard<std::mutex> _(mutex_);
  commands_.emplace("onReceiveRobotCommand", [=](Socket&, Socket& udp_socket) {
    research_interface::RobotCommand robot_command;
    udp_socket.receiveBytes(&robot_command, sizeof(robot_command));
    on_receive_robot_command(robot_command);
  });
  return *this;
}

void MockServer::spinOnce(bool block) {
  std::unique_lock<std::mutex> lock(mutex_);
  continue_ = true;
  cv_.notify_one();
  if (block) {
    cv_.wait(lock, [this]() { return !continue_; });
  }
}

void MockServer::serverThread() {
  std::unique_lock<std::mutex> lock(mutex_);

  const std::string kHostname = "localhost";
  Poco::Net::ServerSocket srv;

  srv =
      Poco::Net::ServerSocket({kHostname, research_interface::kCommandPort});  // does bind + listen
  initialized_ = true;

  cv_.notify_one();
  cv_.wait(lock, [this] { return continue_; });

  Poco::Net::SocketAddress remote_address;
  Poco::Net::StreamSocket tcp_socket = srv.acceptConnection(remote_address);
  tcp_socket.setBlocking(true);
  tcp_socket.setNoDelay(true);

  Socket tcp_socket_wrapper;
  tcp_socket_wrapper.sendBytes = [&](const void* data, size_t size) {
    int rv = tcp_socket.sendBytes(data, size);
    ASSERT_EQ(static_cast<int>(size), rv) << "Send error on TCP socket";
  };
  tcp_socket_wrapper.receiveBytes = [&](void* data, size_t size) {
    int rv = tcp_socket.receiveBytes(data, size);
    ASSERT_EQ(static_cast<int>(size), rv) << "Receive error on TCP socket";
  };

  uint16_t udp_port;
  handleCommand<research_interface::Connect>(
      tcp_socket_wrapper, [&, this](const research_interface::Connect::Request& request) {
        udp_port = request.udp_port;
        return on_connect_ ? on_connect_(request)
                           : research_interface::Connect::Response(
                                 research_interface::Connect::Status::kSuccess);
      });

  Poco::Net::DatagramSocket udp_socket({kHostname, 0});
  udp_socket.setBlocking(true);
  Socket udp_socket_wrapper;
  udp_socket_wrapper.sendBytes = [&](const void* data, size_t size) {
    int rv = udp_socket.sendTo(data, size, {remote_address.host(), udp_port});
    ASSERT_EQ(static_cast<int>(size), rv) << "Send error on UDP socket";
  };
  udp_socket_wrapper.receiveBytes = [&](void* data, size_t size) {
    int rv = udp_socket.receiveFrom(data, size, remote_address);
    ASSERT_EQ(static_cast<int>(size), rv) << "Receive error on UDP socket";
  };

  while (!shutdown_) {
    cv_.wait(lock, [this] { return continue_ || shutdown_; });
    while (!commands_.empty()) {
      commands_.front().second(tcp_socket_wrapper, udp_socket_wrapper);
      commands_.pop();
    }

    ASSERT_FALSE(udp_socket.poll(Poco::Timespan(), Poco::Net::Socket::SelectMode::SELECT_READ)) << "UDP socket still has data";

    if (tcp_socket.poll(Poco::Timespan(), Poco::Net::Socket::SelectMode::SELECT_READ)) {
      // Received something on the TCP socket.
      // Test that the Robot closed the connection.
      std::array<uint8_t, 16> buffer;

      int rv = tcp_socket.receiveBytes(buffer.data(), buffer.size());
      ASSERT_EQ(0, rv) << "TCP socket still has data";
    }

    continue_ = false;
    cv_.notify_one();
  }
}
<|endoftext|>


<commit_before>#include <map>
#include <memory>
#include <algorithm>
#include <cassert>
#include <gtest/gtest.h>

#include "testlog.h"
#include "fake_modbus.h"

class ModbusClientTest: public TLoggedFixture
{
protected:
    void SetUp();
    void TearDown();
    PFakeModbusConnector Connector;
    PModbusClient ModbusClient;
    PFakeSlave Slave;
};

void ModbusClientTest::SetUp()
{
    TModbusConnectionSettings settings("/dev/ttyWhatever", 115200, 'N', 8, 1);
    Connector = PFakeModbusConnector(new TFakeModbusConnector(settings, *this));
    ModbusClient = PModbusClient(new TModbusClient(settings, Connector));
    ModbusClient->SetCallback([this](const TModbusRegister& reg) {
            Emit() << "Modbus Callback: " << reg.ToString() << " becomes " <<
                ModbusClient->GetTextValue(reg);
        });
    Slave = Connector->AddSlave(1,
                                TRegisterRange(0, 10),
                                TRegisterRange(10, 20),
                                TRegisterRange(20, 30),
                                TRegisterRange(30, 40));
}

void ModbusClientTest::TearDown()
{
    ModbusClient.reset();
    Connector.reset();
    TLoggedFixture::TearDown();
}

TEST_F(ModbusClientTest, Poll)
{
    ModbusClient->AddRegister(TModbusRegister(1, TModbusRegister::COIL, 0));
    ModbusClient->AddRegister(TModbusRegister(1, TModbusRegister::COIL, 1));
    ModbusClient->AddRegister(TModbusRegister(1, TModbusRegister::DISCRETE_INPUT, 10));
    ModbusClient->AddRegister(TModbusRegister(1, TModbusRegister::HOLDING_REGISTER, 22));
    ModbusClient->AddRegister(TModbusRegister(1, TModbusRegister::INPUT_REGISTER, 33));

    ModbusClient->Connect();

    Note() << "Cycle()";
    ModbusClient->Cycle();

    Slave->Coils[1] = 1;
    Slave->Discrete[10] = 1;
    Slave->Holding[22] = 4242;
    Slave->Input[33] = 42000;

    Note() << "Cycle()";
    ModbusClient->Cycle();

    EXPECT_EQ(0, ModbusClient->GetRawValue(
        TModbusRegister(1, TModbusRegister::COIL, 0)));
    EXPECT_EQ(1, ModbusClient->GetRawValue(
        TModbusRegister(1, TModbusRegister::COIL, 1)));
    EXPECT_EQ(1, ModbusClient->GetRawValue(
        TModbusRegister(1, TModbusRegister::DISCRETE_INPUT, 10)));
    EXPECT_EQ(4242, ModbusClient->GetRawValue(
        TModbusRegister(1, TModbusRegister::HOLDING_REGISTER, 22)));
    EXPECT_EQ(42000, ModbusClient->GetRawValue(
        TModbusRegister(1, TModbusRegister::INPUT_REGISTER, 33)));
}

TEST_F(ModbusClientTest, Write)
{
    TModbusRegister coil1(1, TModbusRegister::COIL, 1);
    TModbusRegister holding20(1, TModbusRegister::HOLDING_REGISTER, 20);
    ModbusClient->AddRegister(coil1);
    ModbusClient->AddRegister(holding20);

    Note() << "Cycle()";
    ModbusClient->Cycle();

    ModbusClient->SetTextValue(coil1, "1");
    ModbusClient->SetTextValue(holding20, "4242");

    for (int i = 0; i < 3; ++i) {
        Note() << "Cycle()";
        ModbusClient->Cycle();

        EXPECT_EQ(1, ModbusClient->GetRawValue(coil1));
        EXPECT_EQ(1, Slave->Coils[1]);
        EXPECT_EQ(4242, ModbusClient->GetRawValue(holding20));
        EXPECT_EQ(4242, Slave->Holding[20]);
    }
}
<commit_msg>test: simplified modbus poll test a bit.<commit_after>#include <map>
#include <memory>
#include <algorithm>
#include <cassert>
#include <gtest/gtest.h>

#include "testlog.h"
#include "fake_modbus.h"

class ModbusClientTest: public TLoggedFixture
{
protected:
    void SetUp();
    void TearDown();
    PFakeModbusConnector Connector;
    PModbusClient ModbusClient;
    PFakeSlave Slave;
};

void ModbusClientTest::SetUp()
{
    TModbusConnectionSettings settings("/dev/ttyWhatever", 115200, 'N', 8, 1);
    Connector = PFakeModbusConnector(new TFakeModbusConnector(settings, *this));
    ModbusClient = PModbusClient(new TModbusClient(settings, Connector));
    ModbusClient->SetCallback([this](const TModbusRegister& reg) {
            Emit() << "Modbus Callback: " << reg.ToString() << " becomes " <<
                ModbusClient->GetTextValue(reg);
        });
    Slave = Connector->AddSlave(1,
                                TRegisterRange(0, 10),
                                TRegisterRange(10, 20),
                                TRegisterRange(20, 30),
                                TRegisterRange(30, 40));
}

void ModbusClientTest::TearDown()
{
    ModbusClient.reset();
    Connector.reset();
    TLoggedFixture::TearDown();
}

TEST_F(ModbusClientTest, Poll)
{
    TModbusRegister coil0(1, TModbusRegister::COIL, 0);
    TModbusRegister coil1(1, TModbusRegister::COIL, 1);
    TModbusRegister discrete10(1, TModbusRegister::DISCRETE_INPUT, 10);
    TModbusRegister holding22(1, TModbusRegister::HOLDING_REGISTER, 22);
    TModbusRegister input33(1, TModbusRegister::INPUT_REGISTER, 33);

    ModbusClient->AddRegister(coil0);
    ModbusClient->AddRegister(coil1);
    ModbusClient->AddRegister(discrete10);
    ModbusClient->AddRegister(holding22);
    ModbusClient->AddRegister(input33);

    ModbusClient->Connect();

    Note() << "Cycle()";
    ModbusClient->Cycle();

    Slave->Coils[1] = 1;
    Slave->Discrete[10] = 1;
    Slave->Holding[22] = 4242;
    Slave->Input[33] = 42000;

    Note() << "Cycle()";
    ModbusClient->Cycle();

    EXPECT_EQ(0, ModbusClient->GetRawValue(coil0));
    EXPECT_EQ(1, ModbusClient->GetRawValue(coil1));
    EXPECT_EQ(1, ModbusClient->GetRawValue(discrete10));
    EXPECT_EQ(4242, ModbusClient->GetRawValue(holding22));
    EXPECT_EQ(42000, ModbusClient->GetRawValue(input33));
}

TEST_F(ModbusClientTest, Write)
{
    TModbusRegister coil1(1, TModbusRegister::COIL, 1);
    TModbusRegister holding20(1, TModbusRegister::HOLDING_REGISTER, 20);
    ModbusClient->AddRegister(coil1);
    ModbusClient->AddRegister(holding20);

    Note() << "Cycle()";
    ModbusClient->Cycle();

    ModbusClient->SetTextValue(coil1, "1");
    ModbusClient->SetTextValue(holding20, "4242");

    for (int i = 0; i < 3; ++i) {
        Note() << "Cycle()";
        ModbusClient->Cycle();

        EXPECT_EQ(1, ModbusClient->GetRawValue(coil1));
        EXPECT_EQ(1, Slave->Coils[1]);
        EXPECT_EQ(4242, ModbusClient->GetRawValue(holding20));
        EXPECT_EQ(4242, Slave->Holding[20]);
    }
}
<|endoftext|>


<commit_before>/*
 * shapes.cpp
 *
 *  Created on: Aug 3, 2011
 *      Author: claudio
 */

#include <GL/glut.h>
#include <vector>
#include <cassert>
#include "cprocessing.hpp"

using namespace cprocessing;

///
/// Represents a polyline with several attributes such as normals and texture coordinates.
///
struct PPath {

	std::vector<PVector> vtx;  ///< An array of vertices
	std::vector<PVector> nrm;  ///< Normals for the vertices
	std::vector<PVector> tex;  ///< Texture coordinates for the vertices
	std::vector<color> fillC; ///< fill color of vertice
	std::vector<color> strokeC;///<stroke color for edge

	PVector curNormal;     ///< Default normal
	PVector curTexCoord;   ///< Default Texture coordinates

	bool useNormal;     ///< Whether a normal was specified during the path construction
	bool useTexCoord;   ///< Whether a set of texture coordinates was specified during the path construction

	/// Constructor
	PPath () {
		curNormal = PVector(0,0,1);
		curTexCoord = PVector(0,0,0);
		useNormal = false;
		useTexCoord = false;
	}

	/// Adds a new point to the path
	void addVertex(const PVector& p) {
		vtx.push_back (p);
		nrm.push_back (curNormal);
		tex.push_back (curTexCoord);

		fillC.push_back(styles[styles.size()-1].fillColor);
		strokeC.push_back(styles[styles.size()-1].strokeColor);
	}

	/// Changes the current normal vector
	void setNormal(const PVector& n) { curNormal = n; useNormal = true; }

	/// Changes the current set of texture coordinates
	void setTexCoord (const PVector& t) { curTexCoord = t; useTexCoord = true; }

	/// Automatically computes normals from vertex positions. This is done computing
	/// triangle normals for groups of 3 vertices.
	/// @arg vstart: First vertex to compute.
	/// @arg vstride: How many vertices are skipped before computing the next normal
	/// @arg fan: Whether to use vtx[0] as first vertex of triangle rather than the
	///           first in the group.
	void setAutoNormals (int vstart, int vstride, bool fan = false) {
		int n = vtx.size(); // Number of normals / vertices
		assert (n == (int) nrm.size());
		int last = -1; // Last vertex which had its normal assigned
		for (int i = vstart; i < n; i+= vstride) {
			// Compute vectors for the last two triangle edges
			PVector v1 = vtx[i-1] - (fan ? vtx[0] : vtx[i-2]);
			PVector v2 = vtx[i] - vtx[i-1];
			// Normal given by the cross product
			PVector nv = v2.cross(v1);
			nv.normalize();
			// Set all vertices since the last to the new normal
			while (last < i) {
				last++;
				nrm [last] = nv;
			}
		}
	}
};

///
/// Some local module variables
///
static PPath shape; ///< Data for current shape
static ShapeMode mode; ///< Current shape type

//typedef stdvector<double> BlendFactor; ///< Blending factors for a cubic bézier
//static stdvector<BlendFactor> bezierBlend; ///< bezierDetail samples of Bézier blending functions

namespace cprocessing {

	/// Starts the definition of a shape
	void beginShape(ShapeMode mode) {
		PPath newshape;
		shape = newshape;
		mode = mode;
	}

	/// Finishes and renders the shape

	void endShape() {
		if(mode != NULL) glBegin(mode);
		else 			 glBegin(GL_POLYGON);

		for(uint i=0; i<shape.vtx.size(); i++) {
			if(shape.fillC[i].rgba[3] > 0) {
				glColor4ubv (shape.fillC[i].rgba);
				glVertex3d(shape.vtx[i].x, shape.vtx[i].y, shape.vtx[i].z);
			}
		}
		glEnd();

		glBegin(GL_LINE_STRIP);
		for(uint i=0; i<shape.vtx.size(); i++) {
			if(shape.strokeC[i].rgba[3] > 0) {
				glColor4ubv (shape.strokeC[i].rgba);
				glVertex3d(shape.vtx[i].x, shape.vtx[i].y, shape.vtx[i].z);
			}
		}
		if(shape.strokeC[shape.strokeC.size()-1].rgba[3] > 0) {
			glColor4ubv (shape.strokeC[shape.vtx.size()-1].rgba);
			glVertex3d(shape.vtx[0].x, shape.vtx[0].y, shape.vtx[0].z);
		}
		glEnd();
	}

	/// Adds a vertex to the shape
	void vertex (double x, double y, double z) {
		shape.addVertex (PVector(x,y,z));
	}

	/// Specifies a normal for the next vertices
	void normal (double x, double y, double z) {
		shape.setNormal (PVector (x,y,z));
	}

	///
	/// Functions to handle Bézier curves
	///

    /// Establishes the Bézier level of detail, i.e., the number of points
    /// per Bézier curve segment.
	void bezierDetail(int n)
	{
		// Remember the argument
		assert (n > 0);
	    styles[styles.size()-1].bezierDetail = n;
	    // Precompute blending factors
	    styles[styles.size()-1].bezierBlend.clear();
	    double t;
	    double u;
	    for (int i=0; i < n+1; i++) {
	    	t = double(i)/n;
	    	u = 1 - t;
	    	BlendFactor blend;
	    	blend.push_back (u*u*u);
	    	blend.push_back (3*u*u*t);
	    	blend.push_back (3*t*t*u);
	    	blend.push_back (t*t*t);
	    	styles[styles.size()-1].bezierBlend.push_back(blend);
	    }
	}

    /// Given the x or y coordinate of Bézier control points a,b,c,d and
    /// the value of the t parameter, return the corresponding
    /// coordinate of the point.
	double bezierPoint (double a, double b, double c, double d,double t)
	{
	    double u = 1.0 - t;
	    return a*u*u*u + b*3*u*u*t + c*3*t*t*u + d*t*t*t;
	}

	/// Given the x or y coordinate of Bézier control points a,b,c,d and
	/// the value of the t parameter, return the corresponding
	/// coordinate of the tangent at that point."""
	double bezierTangent (double a,double b,double c,double d,double t)
	{
	    double u = 1.0 - t;
	    return -a*3*u*u + b*(9*u*u-6*u) + c*(6*t-9*t*t) + d*3*t*t;
	}

	/// Generates a cubic bezier arc. Arguments are of the form
	/// (cx1, cy1, cz1, cx2, cy2, cz2, x, y, z), i.e. coordinates
	/// for 3 control points in 3D. The first control point of the
	/// arc is the last point of the previous arc or the last vertex.
	void bezierVertex(double cx1, double cy1, double cz1,
			          double cx2, double cy2, double cz2,
			          double x, double y, double z)
	{

		// Ignore if at least one vertex was not issued before
	    if (shape.vtx.size() == 0) return;

	    // Obtain the 4 control points
	    PVector a = shape.vtx[shape.vtx.size()-1];
	    PVector b = PVector (cx1, cy1, cz1);
	    PVector c = PVector (cx2, cy2, cz2);
	    PVector d = PVector (x, y, z);

	    // Put into shape a sampling of the curve
	    for (unsigned i = 0; i < styles[styles.size()-1].bezierBlend.size(); i++) {
	    	BlendFactor factor = styles[styles.size()-1].bezierBlend[i];
	    	PVector p = a*factor[0] + b*factor[1] + c*factor[2] + d*factor[3];
	    	shape.addVertex (p);
	    }
	}

	/// Draws a cubic Bézier curve for the 4 control points
	void bezier(double x1, double y1, double z1, double cx1, double cy1, double cz1,
				double cx2, double cy2, double cz2, double x2, double y2, double z2) {
		beginShape();
		vertex (x1, y1, z1);
		bezierVertex(cx1, cy1, cz1, cx2, cy2, cz2, x2, y2, z2);
		endShape();
	}
}
<commit_msg>shapemode to GL_(shapemode) switcharoo<commit_after>/*
 * shapes.cpp
 *
 *  Created on: Aug 3, 2011
 *      Author: claudio
 */

#include <GL/glut.h>
#include <vector>
#include <cassert>
#include "cprocessing.hpp"

using namespace cprocessing;

///
/// Represents a polyline with several attributes such as normals and texture coordinates.
///
struct PPath {

	std::vector<PVector> vtx;  ///< An array of vertices
	std::vector<PVector> nrm;  ///< Normals for the vertices
	std::vector<PVector> tex;  ///< Texture coordinates for the vertices
	std::vector<color> fillC; ///< fill color of vertice
	std::vector<color> strokeC;///<stroke color for edge

	PVector curNormal;     ///< Default normal
	PVector curTexCoord;   ///< Default Texture coordinates

	bool useNormal;     ///< Whether a normal was specified during the path construction
	bool useTexCoord;   ///< Whether a set of texture coordinates was specified during the path construction

	/// Constructor
	PPath () {
		curNormal = PVector(0,0,1);
		curTexCoord = PVector(0,0,0);
		useNormal = false;
		useTexCoord = false;
	}

	/// Adds a new point to the path
	void addVertex(const PVector& p) {
		vtx.push_back (p);
		nrm.push_back (curNormal);
		tex.push_back (curTexCoord);

		fillC.push_back(styles[styles.size()-1].fillColor);
		strokeC.push_back(styles[styles.size()-1].strokeColor);
	}

	/// Changes the current normal vector
	void setNormal(const PVector& n) { curNormal = n; useNormal = true; }

	/// Changes the current set of texture coordinates
	void setTexCoord (const PVector& t) { curTexCoord = t; useTexCoord = true; }

	/// Automatically computes normals from vertex positions. This is done computing
	/// triangle normals for groups of 3 vertices.
	/// @arg vstart: First vertex to compute.
	/// @arg vstride: How many vertices are skipped before computing the next normal
	/// @arg fan: Whether to use vtx[0] as first vertex of triangle rather than the
	///           first in the group.
	void setAutoNormals (int vstart, int vstride, bool fan = false) {
		int n = vtx.size(); // Number of normals / vertices
		assert (n == (int) nrm.size());
		int last = -1; // Last vertex which had its normal assigned
		for (int i = vstart; i < n; i+= vstride) {
			// Compute vectors for the last two triangle edges
			PVector v1 = vtx[i-1] - (fan ? vtx[0] : vtx[i-2]);
			PVector v2 = vtx[i] - vtx[i-1];
			// Normal given by the cross product
			PVector nv = v2.cross(v1);
			nv.normalize();
			// Set all vertices since the last to the new normal
			while (last < i) {
				last++;
				nrm [last] = nv;
			}
		}
	}
};

///
/// Some local module variables
///
static PPath shape; ///< Data for current shape
ShapeMode shapemode; ///< Current shape type

//typedef stdvector<double> BlendFactor; ///< Blending factors for a cubic bézier
//static stdvector<BlendFactor> bezierBlend; ///< bezierDetail samples of Bézier blending functions

namespace cprocessing {

	/// Starts the definition of a shape
	void beginShape(ShapeMode mode) {
		PPath newshape;
		shape = newshape;
		shapemode = mode;
	}

	/// Finishes and renders the shape

	void endShape() {
		switch(shapemode) {
			case POINTS: 			glBegin(GL_POINTS);	 			break;
			case LINES: 			glBegin(GL_LINES);				break;
			case LINE_LOOP: 		glBegin(GL_LINE_LOOP);			break;
			case LINE_STRIP: 		glBegin(GL_LINE_STRIP); 		break;
			case TRIANGLES:			glBegin(GL_TRIANGLES); 			break;
			case TRIANGLE_STRIP:	glBegin(GL_TRIANGLE_STRIP);		break;
			case TRIANGLE_FAN:		glBegin(GL_TRIANGLE_FAN);		break;
			case QUADS:				glBegin(GL_QUADS);				break;
			case QUAD_STRIP: 		glBegin(GL_QUAD_STRIP);			break;
			case POLYGON:			glBegin(GL_POLYGON);			break;

			default: glBegin(GL_POLYGON);	break;
		}

		for(uint i=0; i<shape.vtx.size(); i++) {
			if(shape.fillC[i].rgba[3] > 0) {
				glColor4ubv (shape.fillC[i].rgba);
				glVertex3d(shape.vtx[i].x, shape.vtx[i].y, shape.vtx[i].z);
			}
		}
		glEnd();

		glBegin(GL_LINE_STRIP);
		for(uint i=0; i<shape.vtx.size(); i++) {
			if(shape.strokeC[i].rgba[3] > 0) {
				glColor4ubv (shape.strokeC[i].rgba);
				glVertex3d(shape.vtx[i].x, shape.vtx[i].y, shape.vtx[i].z);
			}
		}
		if(shape.strokeC[shape.strokeC.size()-1].rgba[3] > 0) {
			glColor4ubv (shape.strokeC[shape.vtx.size()-1].rgba);
			glVertex3d(shape.vtx[0].x, shape.vtx[0].y, shape.vtx[0].z);
		}
		glEnd();
	}

	/// Adds a vertex to the shape
	void vertex (double x, double y, double z) {
		shape.addVertex (PVector(x,y,z));
	}

	/// Specifies a normal for the next vertices
	void normal (double x, double y, double z) {
		shape.setNormal (PVector (x,y,z));
	}

	///
	/// Functions to handle Bézier curves
	///

    /// Establishes the Bézier level of detail, i.e., the number of points
    /// per Bézier curve segment.
	void bezierDetail(int n)
	{
		// Remember the argument
		assert (n > 0);
	    styles[styles.size()-1].bezierDetail = n;
	    // Precompute blending factors
	    styles[styles.size()-1].bezierBlend.clear();
	    double t;
	    double u;
	    for (int i=0; i < n+1; i++) {
	    	t = double(i)/n;
	    	u = 1 - t;
	    	BlendFactor blend;
	    	blend.push_back (u*u*u);
	    	blend.push_back (3*u*u*t);
	    	blend.push_back (3*t*t*u);
	    	blend.push_back (t*t*t);
	    	styles[styles.size()-1].bezierBlend.push_back(blend);
	    }
	}

    /// Given the x or y coordinate of Bézier control points a,b,c,d and
    /// the value of the t parameter, return the corresponding
    /// coordinate of the point.
	double bezierPoint (double a, double b, double c, double d,double t)
	{
	    double u = 1.0 - t;
	    return a*u*u*u + b*3*u*u*t + c*3*t*t*u + d*t*t*t;
	}

	/// Given the x or y coordinate of Bézier control points a,b,c,d and
	/// the value of the t parameter, return the corresponding
	/// coordinate of the tangent at that point."""
	double bezierTangent (double a,double b,double c,double d,double t)
	{
	    double u = 1.0 - t;
	    return -a*3*u*u + b*(9*u*u-6*u) + c*(6*t-9*t*t) + d*3*t*t;
	}

	/// Generates a cubic bezier arc. Arguments are of the form
	/// (cx1, cy1, cz1, cx2, cy2, cz2, x, y, z), i.e. coordinates
	/// for 3 control points in 3D. The first control point of the
	/// arc is the last point of the previous arc or the last vertex.
	void bezierVertex(double cx1, double cy1, double cz1,
			          double cx2, double cy2, double cz2,
			          double x, double y, double z)
	{

		// Ignore if at least one vertex was not issued before
	    if (shape.vtx.size() == 0) return;

	    // Obtain the 4 control points
	    PVector a = shape.vtx[shape.vtx.size()-1];
	    PVector b = PVector (cx1, cy1, cz1);
	    PVector c = PVector (cx2, cy2, cz2);
	    PVector d = PVector (x, y, z);

	    // Put into shape a sampling of the curve
	    for (unsigned i = 0; i < styles[styles.size()-1].bezierBlend.size(); i++) {
	    	BlendFactor factor = styles[styles.size()-1].bezierBlend[i];
	    	PVector p = a*factor[0] + b*factor[1] + c*factor[2] + d*factor[3];
	    	shape.addVertex (p);
	    }
	}

	/// Draws a cubic Bézier curve for the 4 control points
	void bezier(double x1, double y1, double z1, double cx1, double cy1, double cz1,
				double cx2, double cy2, double cz2, double x2, double y2, double z2) {
		beginShape();
		vertex (x1, y1, z1);
		bezierVertex(cx1, cy1, cz1, cx2, cy2, cz2, x2, y2, z2);
		endShape();
	}
}
<|endoftext|>


<commit_before>/*
 * server_test.cpp - Kurento Media Server
 *
 * Copyright (C) 2013 Kurento
 * Contact: Miguel París Díaz <mparisdiaz@gmail.com>
 * Contact: José Antonio Santos Cadenas <santoscadenas@kurento.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "server_test_base.hpp"

#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>
#define BOOST_TEST_MODULE ServerTest

#include <sys/socket.h>
#include <arpa/inet.h>

#include "MediaServerService.h"

#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>

#include <gst/gst.h>

#include "media_config_loader.hpp"
#include "mediaServer_constants.h"
#include "mediaServer_types.h"

using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;

using namespace kurento;

#define GST_CAT_DEFAULT _server_test_
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "server_test"

BOOST_AUTO_TEST_SUITE ( server_test_suite )

static void
check_version (kurento::MediaServerServiceClient client)
{
  int32_t v;
  int32_t gotVersion;
  mediaServerConstants *c;

  c = new mediaServerConstants();
  v = c->VERSION;
  delete c;

  gotVersion = client.getVersion();
  BOOST_CHECK_EQUAL (gotVersion, v);
}

static void
check_type (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject mo = MediaObject();

  client.createMediaManager (mediaManager, 0);
  BOOST_CHECK (mediaManager.type.__isset.mediaObject);
  BOOST_CHECK_EQUAL (mediaManager.type.mediaObject, MediaObjectType::type::MEDIA_MANAGER);

  client.createSdpEndPoint (mo, mediaManager, SdpEndPointType::type::RTP_END_POINT);
  BOOST_CHECK (mediaManager.type.__isset.sdpEndPoint);
  BOOST_CHECK_EQUAL (mo.type.sdpEndPoint, SdpEndPointType::type::RTP_END_POINT);

  client.createSdpEndPoint (mo, mediaManager, SdpEndPointType::type::WEBRTC_END_POINT);
  BOOST_CHECK (mediaManager.type.__isset.sdpEndPoint);
  BOOST_CHECK_EQUAL (mo.type.sdpEndPoint, SdpEndPointType::type::WEBRTC_END_POINT);

  client.createUriEndPoint (mo, mediaManager, UriEndPointType::type::PLAYER_END_POINT, "");
  BOOST_CHECK (mediaManager.type.__isset.uriEndPoint);
  BOOST_CHECK_EQUAL (mo.type.uriEndPoint, UriEndPointType::type::PLAYER_END_POINT);

  client.createUriEndPoint (mo, mediaManager, UriEndPointType::type::RECORDER_END_POINT, "");
  BOOST_CHECK (mediaManager.type.__isset.uriEndPoint);
  BOOST_CHECK_EQUAL (mo.type.uriEndPoint, UriEndPointType::type::RECORDER_END_POINT);

  client.createHttpEndPoint (mo, mediaManager);
  BOOST_CHECK (mediaManager.type.__isset.endPoint);
  BOOST_CHECK_EQUAL (mo.type.endPoint, EndPointType::type::HTTP_END_POINT);

  client.createMixer (mo, mediaManager, MixerType::type::MAIN_MIXER);
  BOOST_CHECK (mediaManager.type.__isset.mixerType);
  BOOST_CHECK_EQUAL (mo.type.mixerType, MixerType::type::MAIN_MIXER);

  client.release (mediaManager);
}

static void
check_same_token (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject mo = MediaObject();

  client.createMediaManager (mediaManager, 0);

  client.createMixer (mo, mediaManager, MixerType::type::MAIN_MIXER);
  BOOST_CHECK_EQUAL (mediaManager.token, mo.token);

  client.createSdpEndPoint (mo, mediaManager, SdpEndPointType::type::RTP_END_POINT);
  BOOST_CHECK_EQUAL (mediaManager.token, mo.token);

  client.createSdpEndPoint (mo, mediaManager, SdpEndPointType::type::WEBRTC_END_POINT);
  BOOST_CHECK_EQUAL (mediaManager.token, mo.token);

  client.release (mediaManager);
}

static void
check_use_released_media_manager (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject mo = MediaObject();

  client.createMediaManager (mediaManager, 0);
  client.release (mediaManager);
  BOOST_CHECK_THROW (client.createMixer (mo, mediaManager, MixerType::type::MAIN_MIXER), MediaObjectNotFoundException);
}

static void
check_parent (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject mo = MediaObject();
  MediaObject parent = MediaObject();

  client.createMediaManager (mediaManager, 0);

  client.createMixer (mo, mediaManager, MixerType::type::MAIN_MIXER);
  client.getParent (parent, mo);
  BOOST_CHECK_EQUAL (mediaManager.id, parent.id);

  client.release (mediaManager);
}

static void
check_media_manager_no_parent (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject parent = MediaObject();

  GST_DEBUG ("check_media_manager_no_parent test");
  client.createMediaManager (mediaManager, 0);
  BOOST_CHECK_THROW (client.getParent (parent, mediaManager), NoParentException);

  client.release (mediaManager);
}

static void
check_sdp_end_point (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject sdpEp = MediaObject();
  std::string out;

  client.createMediaManager (mediaManager, 0);

  client.createSdpEndPoint (sdpEp, mediaManager, SdpEndPointType::type::RTP_END_POINT);
  client.generateOffer (out, sdpEp);
  GST_INFO ("RTP EndPoint generateOffer: %s", out.c_str () );
  client.processOffer (out, sdpEp, "");
  GST_INFO ("RTP EndPoint processOffer: %s", out.c_str () );
  client.processAnswer (out, sdpEp, "");
  GST_INFO ("RTP EndPoint processAnswer: %s", out.c_str () );

  client.createSdpEndPointWithFixedSdp (sdpEp, mediaManager, SdpEndPointType::type::RTP_END_POINT, "");
  client.generateOffer (out, sdpEp);
  GST_INFO ("RTP EndPoint generateOffer: %s", out.c_str () );
  client.processOffer (out, sdpEp, "");
  GST_INFO ("RTP EndPoint processOffer: %s", out.c_str () );
  client.processAnswer (out, sdpEp, "");
  GST_INFO ("RTP EndPoint processAnswer: %s", out.c_str () );

  client.createSdpEndPoint (sdpEp, mediaManager, SdpEndPointType::type::WEBRTC_END_POINT);
  client.generateOffer (out, sdpEp);
  GST_INFO ("WebRTC EndPoint generateOffer: %s", out.c_str () );
  client.processOffer (out, sdpEp, "");
  GST_INFO ("WebRTC EndPoint processOffer: %s", out.c_str () );
  client.processAnswer (out, sdpEp, "");
  GST_INFO ("WebRTC EndPoint processAnswer: %s", out.c_str () );

  client.createSdpEndPointWithFixedSdp (sdpEp, mediaManager, SdpEndPointType::type::WEBRTC_END_POINT, "");
  client.generateOffer (out, sdpEp);
  GST_INFO ("WebRTC EndPoint generateOffer: %s", out.c_str () );
  client.processOffer (out, sdpEp, "");
  GST_INFO ("WebRTC EndPoint processOffer: %s", out.c_str () );
  client.processAnswer (out, sdpEp, "");
  GST_INFO ("WebRTC EndPoint processAnswer: %s", out.c_str () );

  client.release (mediaManager);
}

static void
check_uri_end_point (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject uriEp = MediaObject();
  std::string uri, out;

  client.createMediaManager (mediaManager, 0);

  uri = "/player_end_point/uri";
  client.createUriEndPoint (uriEp, mediaManager, UriEndPointType::type::PLAYER_END_POINT, uri);
  client.getUri (out, uriEp);
  BOOST_CHECK_EQUAL (uri, out);
  client.start (uriEp);
  client.pause (uriEp);
  client.stop (uriEp);

  uri = "/recorder_end_point/uri";
  client.createUriEndPoint (uriEp, mediaManager, UriEndPointType::type::RECORDER_END_POINT, uri);
  client.getUri (out, uriEp);
  BOOST_CHECK_EQUAL (uri, out);
  client.start (uriEp);
  client.pause (uriEp);
  client.stop (uriEp);

  client.release (mediaManager);
}

static void
check_http_end_point (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject httpEp = MediaObject();
  std::string out;

  client.createMediaManager (mediaManager, 0);

  client.createHttpEndPoint (httpEp, mediaManager);
  client.getUrl (out, httpEp);

  client.release (mediaManager);
}

static void
client_side ()
{
  boost::shared_ptr<TSocket> socket (new TSocket (MEDIA_SERVER_ADDRESS, MEDIA_SERVER_SERVICE_PORT) );
  boost::shared_ptr<TTransport> transport (new TFramedTransport (socket) );
  boost::shared_ptr<TProtocol> protocol (new TBinaryProtocol (transport) );
  kurento::MediaServerServiceClient client (protocol);

  transport->open ();

  check_version (client);
  check_use_released_media_manager (client);
  check_type (client);
  check_same_token (client);
  check_parent (client);
  check_media_manager_no_parent (client);
  check_sdp_end_point (client);
  check_uri_end_point (client);
  check_http_end_point (client);

  transport->close ();
}

BOOST_AUTO_TEST_CASE ( server_test )
{
  gst_init (NULL, NULL);

  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
      GST_DEFAULT_NAME);

  START_SERVER_TEST();
  client_side();
  STOP_SERVER_TEST();
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Add test for addHandlerAddress<commit_after>/*
 * server_test.cpp - Kurento Media Server
 *
 * Copyright (C) 2013 Kurento
 * Contact: Miguel París Díaz <mparisdiaz@gmail.com>
 * Contact: José Antonio Santos Cadenas <santoscadenas@kurento.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "server_test_base.hpp"

#define BOOST_TEST_MAIN

#include <boost/test/unit_test.hpp>
#define BOOST_TEST_MODULE ServerTest

#include <sys/socket.h>
#include <arpa/inet.h>

#include "MediaServerService.h"

#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>

#include <gst/gst.h>

#include "media_config_loader.hpp"
#include "mediaServer_constants.h"
#include "mediaServer_types.h"

using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;

using namespace kurento;

#define GST_CAT_DEFAULT _server_test_
GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
#define GST_DEFAULT_NAME "server_test"

BOOST_AUTO_TEST_SUITE ( server_test_suite )

static void
check_version (kurento::MediaServerServiceClient client)
{
  int32_t v;
  int32_t gotVersion;
  mediaServerConstants *c;

  c = new mediaServerConstants();
  v = c->VERSION;
  delete c;

  gotVersion = client.getVersion();
  BOOST_CHECK_EQUAL (gotVersion, v);
}

static void
check_no_handler (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();

  BOOST_CHECK_THROW (client.createMediaManager (mediaManager, 0), HandlerNotFoundException);
}

static void
check_add_handler_address (kurento::MediaServerServiceClient client)
{
  client.addHandlerAddress (0, "localhost", 2323);
  client.addHandlerAddress (0, "localhost", 3434);
}

static void
check_type (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject mo = MediaObject();

  client.createMediaManager (mediaManager, 0);
  BOOST_CHECK (mediaManager.type.__isset.mediaObject);
  BOOST_CHECK_EQUAL (mediaManager.type.mediaObject, MediaObjectType::type::MEDIA_MANAGER);

  client.createSdpEndPoint (mo, mediaManager, SdpEndPointType::type::RTP_END_POINT);
  BOOST_CHECK (mediaManager.type.__isset.sdpEndPoint);
  BOOST_CHECK_EQUAL (mo.type.sdpEndPoint, SdpEndPointType::type::RTP_END_POINT);

  client.createSdpEndPoint (mo, mediaManager, SdpEndPointType::type::WEBRTC_END_POINT);
  BOOST_CHECK (mediaManager.type.__isset.sdpEndPoint);
  BOOST_CHECK_EQUAL (mo.type.sdpEndPoint, SdpEndPointType::type::WEBRTC_END_POINT);

  client.createUriEndPoint (mo, mediaManager, UriEndPointType::type::PLAYER_END_POINT, "");
  BOOST_CHECK (mediaManager.type.__isset.uriEndPoint);
  BOOST_CHECK_EQUAL (mo.type.uriEndPoint, UriEndPointType::type::PLAYER_END_POINT);

  client.createUriEndPoint (mo, mediaManager, UriEndPointType::type::RECORDER_END_POINT, "");
  BOOST_CHECK (mediaManager.type.__isset.uriEndPoint);
  BOOST_CHECK_EQUAL (mo.type.uriEndPoint, UriEndPointType::type::RECORDER_END_POINT);

  client.createHttpEndPoint (mo, mediaManager);
  BOOST_CHECK (mediaManager.type.__isset.endPoint);
  BOOST_CHECK_EQUAL (mo.type.endPoint, EndPointType::type::HTTP_END_POINT);

  client.createMixer (mo, mediaManager, MixerType::type::MAIN_MIXER);
  BOOST_CHECK (mediaManager.type.__isset.mixerType);
  BOOST_CHECK_EQUAL (mo.type.mixerType, MixerType::type::MAIN_MIXER);

  client.release (mediaManager);
}

static void
check_same_token (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject mo = MediaObject();

  client.createMediaManager (mediaManager, 0);

  client.createMixer (mo, mediaManager, MixerType::type::MAIN_MIXER);
  BOOST_CHECK_EQUAL (mediaManager.token, mo.token);

  client.createSdpEndPoint (mo, mediaManager, SdpEndPointType::type::RTP_END_POINT);
  BOOST_CHECK_EQUAL (mediaManager.token, mo.token);

  client.createSdpEndPoint (mo, mediaManager, SdpEndPointType::type::WEBRTC_END_POINT);
  BOOST_CHECK_EQUAL (mediaManager.token, mo.token);

  client.release (mediaManager);
}

static void
check_use_released_media_manager (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject mo = MediaObject();

  client.createMediaManager (mediaManager, 0);
  client.release (mediaManager);
  BOOST_CHECK_THROW (client.createMixer (mo, mediaManager, MixerType::type::MAIN_MIXER), MediaObjectNotFoundException);
}

static void
check_parent (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject mo = MediaObject();
  MediaObject parent = MediaObject();

  client.createMediaManager (mediaManager, 0);

  client.createMixer (mo, mediaManager, MixerType::type::MAIN_MIXER);
  client.getParent (parent, mo);
  BOOST_CHECK_EQUAL (mediaManager.id, parent.id);

  client.release (mediaManager);
}

static void
check_media_manager_no_parent (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject parent = MediaObject();

  GST_DEBUG ("check_media_manager_no_parent test");
  client.createMediaManager (mediaManager, 0);
  BOOST_CHECK_THROW (client.getParent (parent, mediaManager), NoParentException);

  client.release (mediaManager);
}

static void
check_sdp_end_point (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject sdpEp = MediaObject();
  std::string out;

  client.createMediaManager (mediaManager, 0);

  client.createSdpEndPoint (sdpEp, mediaManager, SdpEndPointType::type::RTP_END_POINT);
  client.generateOffer (out, sdpEp);
  GST_INFO ("RTP EndPoint generateOffer: %s", out.c_str () );
  client.processOffer (out, sdpEp, "");
  GST_INFO ("RTP EndPoint processOffer: %s", out.c_str () );
  client.processAnswer (out, sdpEp, "");
  GST_INFO ("RTP EndPoint processAnswer: %s", out.c_str () );

  client.createSdpEndPointWithFixedSdp (sdpEp, mediaManager, SdpEndPointType::type::RTP_END_POINT, "");
  client.generateOffer (out, sdpEp);
  GST_INFO ("RTP EndPoint generateOffer: %s", out.c_str () );
  client.processOffer (out, sdpEp, "");
  GST_INFO ("RTP EndPoint processOffer: %s", out.c_str () );
  client.processAnswer (out, sdpEp, "");
  GST_INFO ("RTP EndPoint processAnswer: %s", out.c_str () );

  client.createSdpEndPoint (sdpEp, mediaManager, SdpEndPointType::type::WEBRTC_END_POINT);
  client.generateOffer (out, sdpEp);
  GST_INFO ("WebRTC EndPoint generateOffer: %s", out.c_str () );
  client.processOffer (out, sdpEp, "");
  GST_INFO ("WebRTC EndPoint processOffer: %s", out.c_str () );
  client.processAnswer (out, sdpEp, "");
  GST_INFO ("WebRTC EndPoint processAnswer: %s", out.c_str () );

  client.createSdpEndPointWithFixedSdp (sdpEp, mediaManager, SdpEndPointType::type::WEBRTC_END_POINT, "");
  client.generateOffer (out, sdpEp);
  GST_INFO ("WebRTC EndPoint generateOffer: %s", out.c_str () );
  client.processOffer (out, sdpEp, "");
  GST_INFO ("WebRTC EndPoint processOffer: %s", out.c_str () );
  client.processAnswer (out, sdpEp, "");
  GST_INFO ("WebRTC EndPoint processAnswer: %s", out.c_str () );

  client.release (mediaManager);
}

static void
check_uri_end_point (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject uriEp = MediaObject();
  std::string uri, out;

  client.createMediaManager (mediaManager, 0);

  uri = "/player_end_point/uri";
  client.createUriEndPoint (uriEp, mediaManager, UriEndPointType::type::PLAYER_END_POINT, uri);
  client.getUri (out, uriEp);
  BOOST_CHECK_EQUAL (uri, out);
  client.start (uriEp);
  client.pause (uriEp);
  client.stop (uriEp);

  uri = "/recorder_end_point/uri";
  client.createUriEndPoint (uriEp, mediaManager, UriEndPointType::type::RECORDER_END_POINT, uri);
  client.getUri (out, uriEp);
  BOOST_CHECK_EQUAL (uri, out);
  client.start (uriEp);
  client.pause (uriEp);
  client.stop (uriEp);

  client.release (mediaManager);
}

static void
check_http_end_point (kurento::MediaServerServiceClient client)
{
  MediaObject mediaManager = MediaObject();
  MediaObject httpEp = MediaObject();
  std::string out;

  client.createMediaManager (mediaManager, 0);

  client.createHttpEndPoint (httpEp, mediaManager);
  client.getUrl (out, httpEp);

  client.release (mediaManager);
}

static void
client_side ()
{
  boost::shared_ptr<TSocket> socket (new TSocket (MEDIA_SERVER_ADDRESS, MEDIA_SERVER_SERVICE_PORT) );
  boost::shared_ptr<TTransport> transport (new TFramedTransport (socket) );
  boost::shared_ptr<TProtocol> protocol (new TBinaryProtocol (transport) );
  kurento::MediaServerServiceClient client (protocol);

  transport->open ();

  check_version (client);
  check_no_handler (client);
  check_add_handler_address (client);
  check_use_released_media_manager (client);
  check_type (client);
  check_same_token (client);
  check_parent (client);
  check_media_manager_no_parent (client);
  check_sdp_end_point (client);
  check_uri_end_point (client);
  check_http_end_point (client);

  transport->close ();
}

BOOST_AUTO_TEST_CASE ( server_test )
{
  gst_init (NULL, NULL);

  GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, GST_DEFAULT_NAME, 0,
      GST_DEFAULT_NAME);

  START_SERVER_TEST();
  client_side();
  STOP_SERVER_TEST();
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>