Skip to content
Merged
57 changes: 21 additions & 36 deletions apps/osvr_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,16 @@
#include <osvr/Util/Logger.h>
#include <osvr/Util/LogNames.h>
#include <osvr/Util/LogRegistry.h>
#include <osvr/Server/ConfigFilePaths.h>

// Library/third-party includes
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/optional.hpp>

// Standard includes
#include <exception>
#include <fstream>
#include <vector>
#include <iostream>

namespace opt = boost::program_options;
namespace fs = boost::filesystem;

static osvr::server::ServerPtr server;
using ::osvr::util::log::OSVR_SERVER_LOG;
Expand All @@ -57,19 +53,15 @@ void handleShutdown() {
int main(int argc, char *argv[]) {
auto log = ::osvr::util::log::make_logger(OSVR_SERVER_LOG);

std::string configName; // server configuration filename
std::vector<std::string> configPaths;

opt::options_description optionsAll("All Options");
opt::options_description optionsVisible("Command Line Options");
opt::positional_options_description optionsPositional;

optionsPositional.add("config", -1);
optionsAll.add_options()(
"config",
opt::value<std::string>(&configName)
->default_value(osvr::server::getDefaultConfigFilename()),
"server configuration filename");
optionsVisible.add_options()
("config", "server configuration filename")
("help", "display this help message")
("verbose,v", "enable verbose logging")
("debug,d", "enable debug logging");
Expand Down Expand Up @@ -106,36 +98,29 @@ int main(int argc, char *argv[]) {
log->debug("Verbose logging enabled.");
}

configName = values["config"].as<std::string>();
if (values.count("config")) {
std::string configFileArgument = values["config"].as<std::string>();
log->info() << "Using config file " << configFileArgument << " from command line argument.";
configPaths = { configFileArgument };
} else {
log->info() << "Using default config file - pass a filename on the command "
"line to use a different one.";
configPaths = osvr::server::getDefaultConfigFilePaths();
}

boost::optional<fs::path> configPath(configName);
try {
if (!fs::exists(*configPath)) {
log->warn() << "File '" << configName
<< "' not found. Using empty configuration.";
configPath = boost::none;
server = osvr::server::configureServerFromFirstFileInList(configPaths);
if (!server) {
// only attempt to load the empty config if no arguments are passed.
if (!values.count("config")) {
log->info() << "Could not find a valid config file in the default search paths. Using default config object.";
server = osvr::server::configureServerFromString("{ }");
} else {
if (fs::is_directory(*configPath)) {
log->error() << "'" << configName << "' is a directory.";
return -1;
} else if (!fs::is_regular_file(*configPath)) {
log->error() << "'" << configName << "' is special file.";
return -1;
}
return -1;
}
} catch (fs::filesystem_error &e) {
log->error() << "Could not open config file at '" << configName << "'.";
log->error() << "Reason " << e.what() << ".";
configPath = boost::none;
}

if (configPath) {
server = osvr::server::configureServerFromFile(configName);
} else {
server = osvr::server::configureServerFromString("{ }");
}

if (!server) {
log->error() << "Unknown error while creating server.";
return -1;
}

Expand Down
45 changes: 45 additions & 0 deletions inc/osvr/Server/ConfigFilePaths.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/** @file
@brief Platform specific search paths for osvr server config files.

@date 2017

@author
Sensics, Inc.
<http://sensics.com/osvr>
*/

// Copyright 2017 Sensics, Inc.
//
// 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.

#ifndef INCLUDED_ConfigFilePaths_h_GUID_241E9C9C_0E0E_46B0_9DED_8F8059306192
#define INCLUDED_ConfigFilePaths_h_GUID_241E9C9C_0E0E_46B0_9DED_8F8059306192

// Internal Includes
#include <osvr/Server/Export.h>

// Library/third-party includes
// - none

// Standard includes
#include <vector>
#include <string>

namespace osvr {
namespace server {

/// @brief this returns a vector of default server configuration file paths.
OSVR_SERVER_EXPORT std::vector<std::string> getDefaultConfigFilePaths();
}
}
#endif // INCLUDED_ConfigFilePaths_h_GUID_241E9C9C_0E0E_46B0_9DED_8F8059306192
130 changes: 14 additions & 116 deletions inc/osvr/Server/ConfigureServerFromFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,133 +35,31 @@
// - none

// Standard includes
#include <exception>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <string>

namespace osvr {
namespace server {

inline const char *getDefaultConfigFilename() {
return "osvr_server_config.json";
}

/// @brief This is the basic common code of a server app's setup, ripped out
/// @brief This uses a file name to attempt to configure the server with
/// that config file.
/// Pass an empty string to use the default config.
/// This is the basic common code of a server app's setup, ripped out
/// of the main server app to make alternate server-acting apps simpler to
/// develop.
inline ServerPtr configureServerFromString(std::string const &json) {
auto log =
::osvr::util::log::make_logger(::osvr::util::log::OSVR_SERVER_LOG);

ServerPtr ret;
osvr::server::ConfigureServer srvConfig;
log->info() << "Constructing server as configured...";
try {
srvConfig.loadConfig(json);
ret = srvConfig.constructServer();
} catch (std::exception &e) {
log->error()
<< "Caught exception constructing server from JSON config "
"file: "
<< e.what();
return nullptr;
}

{
log->info() << "Loading auto-loadable plugins...";
srvConfig.loadAutoPlugins();
}

{
log->info() << "Loading plugins...";
srvConfig.loadPlugins();
if (!srvConfig.getSuccessfulPlugins().empty()) {
log->info() << "Successfully loaded the following plugins:";
for (auto const &plugin : srvConfig.getSuccessfulPlugins()) {
log->info() << " - " << plugin;
}
}
if (!srvConfig.getFailedPlugins().empty()) {
log->warn() << "Failed to load the following plugins:";
for (auto const &pluginError : srvConfig.getFailedPlugins()) {
log->warn() << " - " << pluginError.first << "\t"
<< pluginError.second;
}
}
}

{
log->info() << "Instantiating configured drivers...";
bool success = srvConfig.instantiateDrivers();
if (!srvConfig.getSuccessfulInstantiations().empty()) {
log->info() << "Successes:";
for (auto const &driver :
srvConfig.getSuccessfulInstantiations()) {
log->info() << " - " << driver;
}
}
if (!srvConfig.getFailedInstantiations().empty()) {
log->error() << "Errors:";
for (auto const &error : srvConfig.getFailedInstantiations()) {
log->error() << " - " << error.first << "\t"
<< error.second;
}
}
}

if (srvConfig.processExternalDevices()) {
log->info()
<< "External devices found and parsed from config file.";
}

if (srvConfig.processRoutes()) {
log->info() << "Routes found and parsed from config file.";
}

if (srvConfig.processAliases()) {
log->info() << "Aliases found and parsed from config file.";
}
OSVR_SERVER_EXPORT ServerPtr configureServerFromFile(std::string const &configName);

if (srvConfig.processDisplay()) {
log->info()
<< "Display descriptor found and parsed from config file.";
} else {
log->info()
<< "Using OSVR HDK for display configuration. "
"Did not find an alternate valid 'display' object in config "
"file.";
}
OSVR_SERVER_EXPORT ServerPtr configureServerFromString(std::string const &json);

if (srvConfig.processRenderManagerParameters()) {
log->info() << "RenderManager config found and parsed from the "
"config file.";
}

log->info() << "Triggering automatic hardware detection...";
ret->triggerHardwareDetect();

return ret;
}

/// @Brief Convenience wrapper for configureServerFromString().
inline ServerPtr configureServerFromFile(std::string const &configName) {
auto log =
::osvr::util::log::make_logger(::osvr::util::log::OSVR_SERVER_LOG);

ServerPtr ret;
log->info() << "Using config file '" << configName << "'.";
std::ifstream config(configName);
if (!config.good()) {
log->error() << "Could not open config file!";
log->error() << "Searched in the current directory; file may be "
"misspelled, missing, or in a different directory.";
return nullptr;
}

std::stringstream sstr;
sstr << config.rdbuf();
return configureServerFromString(sstr.str());
}
/// @brief This iterates over a vector that contains a list of potential
/// config files, and uses the first working one to create the server
/// instance.
OSVR_SERVER_EXPORT ServerPtr configureServerFromFirstFileInList(
std::vector<std::string> const &configNames);

} // namespace server
} // namespace osvr
Expand Down
3 changes: 3 additions & 0 deletions src/osvr/Server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ osvr_setup_lib_vars(Server)

set(API
"${HEADER_LOCATION}/ConfigureServer.h"
"${HEADER_LOCATION}/ConfigFilePaths.h"
"${HEADER_LOCATION}/ConfigureServerFromFile.h"
"${HEADER_LOCATION}/Server.h"
"${HEADER_LOCATION}/ServerPtr.h"
Expand All @@ -11,6 +12,8 @@ set(API

set(SOURCE
ConfigureServer.cpp
ConfigFilePaths.cpp
ConfigureServerFromFile.cpp
JSONResolvePossibleRef.h
JSONResolvePossibleRef.cpp
Server.cpp
Expand Down
Loading