ServerImpl::ServerImpl(connection::ConnectionPtr const &conn, boost::optional<std::string> const &host, boost::optional<int> const &port) : m_conn(conn), m_ctx(make_shared<pluginhost::RegistrationContext>()), m_host(host.get_value_or("localhost")), m_port(port.get_value_or(util::UseDefaultPort)), m_log(util::log::make_logger(util::log::OSVR_SERVER_LOG)) { if (!m_conn) { throw std::logic_error( "Can't pass a null ConnectionPtr into Server constructor!"); } osvr::connection::Connection::storeConnection(*m_ctx, m_conn); // Get the underlying VRPN connection, and make sure it's OK. auto vrpnConn = getVRPNConnection(m_conn); if (!(vrpnConn->doing_okay())) { throw ServerCreationFailure(); } // Set up system device/system component m_systemDevice = common::createServerDevice( common::SystemComponent::deviceName(), vrpnConn); m_systemComponent = m_systemDevice->addComponent(common::SystemComponent::create()); m_systemComponent->registerClientRouteUpdateHandler( &ServerImpl::m_handleUpdatedRoute, this); // Things to do when we get a new incoming connection // No longer doing hardware detect unconditionally here - see // triggerHardwareDetect() m_commonComponent = m_systemDevice->addComponent(common::CommonComponent::create()); m_commonComponent->registerPingHandler([&] { m_queueTreeSend(); }); // Set up the default display descriptor. m_tree.getNodeByPath("/display").value() = common::elements::StringElement(util::makeString(display_json)); // Deal with updated device descriptors. m_conn->registerDescriptorHandler([&] { m_handleDeviceDescriptors(); }); // Set up handlers to enter/exit idle sleep mode. // Can't do this with the nice wrappers on the CommonComponent of the // system device, I suppose since people aren't really connecting to // that device. vrpnConn->register_handler( vrpnConn->register_message_type(vrpn_got_first_connection), &ServerImpl::m_exitIdle, this); vrpnConn->register_handler( vrpnConn->register_message_type(vrpn_dropped_last_connection), &ServerImpl::m_enterIdle, this); }
vrpn_File_Connection::vrpn_File_Connection (const char * station_name, const char * local_in_logfile_name, const char * local_out_logfile_name) : vrpn_Connection (local_in_logfile_name, local_out_logfile_name, NULL, NULL), d_controllerId (register_sender("vrpn File Controller")), d_set_replay_rate_type(register_message_type("vrpn_File set_replay_rate")), d_reset_type (register_message_type("vrpn_File reset")), d_play_to_time_type (register_message_type("vrpn_File play_to_time")), d_fileName (NULL), d_file (NULL), d_logHead (NULL), d_logTail (NULL), d_currentLogEntry (NULL), d_preload(vrpn_FILE_CONNECTIONS_SHOULD_PRELOAD), d_accumulate(vrpn_FILE_CONNECTIONS_SHOULD_ACCUMULATE) { // Because we are a file connection, our status should be CONNECTED // Later set this to BROKEN if there is a problem opening/reading the file. if (d_endpoints[0] == NULL) { fprintf(stderr,"vrpn_File_Connection::vrpn_File_Connection(): NULL zeroeth endpoint\n"); } else { connectionStatus = CONNECTED; d_endpoints[0]->status = CONNECTED; } // If we are preloading, then we must accumulate messages. if (d_preload) { d_accumulate = true; } // These are handlers for messages that may be sent from a // vrpn_File_Controller object that may attach itself to us. register_handler(d_set_replay_rate_type, handle_set_replay_rate, this, d_controllerId); register_handler(d_reset_type, handle_reset, this, d_controllerId); register_handler(d_play_to_time_type, handle_play_to_time, this, d_controllerId); // necessary to initialize properly in mainloop() d_last_time.tv_usec = d_last_time.tv_sec = 0; d_fileName = vrpn_copy_file_name(station_name); if (!d_fileName) { fprintf(stderr, "vrpn_File_Connection: Out of memory!\n"); connectionStatus = BROKEN; return; } d_file = fopen(d_fileName, "rb"); if (!d_file) { fprintf(stderr, "vrpn_File_Connection: " "Could not open file \"%s\".\n", d_fileName); connectionStatus = BROKEN; return; } // Read the cookie from the file. It will print an error message if it // can't read it, so we just pass the broken status on up the chain. if (read_cookie() < 0) { connectionStatus = BROKEN; return; } // If we are supposed to preload the entire file into memory buffers, // then keep reading until we get to the end. Otherwise, just read the // first message to get things going. if (d_preload) { while (!read_entry()) { } } else { read_entry(); } // Initialize the "current message" pointer to the first log-file // entry that was read, and set the start time for the file and // the current time to the one in this message. if (d_logHead) { d_currentLogEntry = d_logHead; d_startEntry = d_logHead; d_start_time = d_startEntry->data.msg_time; d_time = d_start_time; d_earliest_user_time.tv_sec = d_earliest_user_time.tv_usec = 0; d_earliest_user_time_valid = false; d_highest_user_time.tv_sec = d_highest_user_time.tv_usec = 0; d_highest_user_time_valid = false; } else { fprintf(stderr, "vrpn_File_Connection: Can't read first message\n"); connectionStatus = BROKEN; return; } // This is useful to play the initial system messages // (the sender/type ones) automatically. These might not be // time synched so if we don't play them automatically they // can mess up playback if their timestamps are later then // the first user message. if (vrpn_FILE_CONNECTIONS_SHOULD_SKIP_TO_USER_MESSAGES) { play_to_user_message(); if (d_currentLogEntry) { d_start_time = d_currentLogEntry->data.msg_time; d_time = d_start_time; } } // Add this to the list of known connections. vrpn_ConnectionManager::instance().addConnection(this, station_name); }