X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=main.cpp;h=d77fb2e357cfbdc2f41c2abfcc3a90e3e5b31695;hp=1f7313ac0eb6c013648d7edafff1e93b99902460;hb=ca9624c43b968a0f29ea44e47851ff686bb64bb6;hpb=d9b0536b128e10447a986f7b6ea2b5c93252c80f diff --git a/main.cpp b/main.cpp index 1f7313a..d77fb2e 100644 --- a/main.cpp +++ b/main.cpp @@ -26,6 +26,7 @@ #include "serverpool.h" #include "input.h" #include "stats.h" +#include "version.h" #include "state.pb.h" using namespace std; @@ -69,8 +70,7 @@ int make_tempfile(const CubemapStateProto &state) } CubemapStateProto collect_state(const timeval &serialize_start, - int server_sock, - int port, + const vector acceptors, const vector inputs, ServerPool *servers, int num_servers) @@ -78,8 +78,10 @@ CubemapStateProto collect_state(const timeval &serialize_start, CubemapStateProto state; state.set_serialize_start_sec(serialize_start.tv_sec); state.set_serialize_start_usec(serialize_start.tv_usec); - state.set_server_sock(server_sock); - state.set_port(port); + + for (size_t i = 0; i < acceptors.size(); ++i) { + state.add_acceptors()->MergeFrom(acceptors[i]->serialize()); + } for (size_t i = 0; i < inputs.size(); ++i) { state.add_inputs()->MergeFrom(inputs[i]->serialize()); @@ -185,7 +187,52 @@ MarkPool *parse_mark_pool(map, MarkPool *> *mark_pools, const str return get_mark_pool(mark_pools, from, to); } - + +// Find all port statements in the configuration file, and create acceptors for htem. +vector create_acceptors( + const vector &config, + map *deserialized_acceptors) +{ + vector acceptors; + for (unsigned i = 0; i < config.size(); ++i) { + if (config[i].keyword != "port") { + continue; + } + if (config[i].arguments.size() != 1) { + fprintf(stderr, "ERROR: 'port' takes exactly one argument\n"); + exit(1); + } + int port = atoi(config[i].arguments[0].c_str()); + if (port < 1 || port >= 65536) { + fprintf(stderr, "WARNING: port %d is out of range (must be [1,65536>), ignoring\n", port); + continue; + } + + Acceptor *acceptor = NULL; + map::iterator deserialized_acceptor_it = + deserialized_acceptors->find(port); + if (deserialized_acceptor_it != deserialized_acceptors->end()) { + acceptor = deserialized_acceptor_it->second; + deserialized_acceptors->erase(deserialized_acceptor_it); + } else { + int server_sock = create_server_socket(port, TCP_SOCKET); + acceptor = new Acceptor(server_sock, port); + } + acceptor->run(); + acceptors.push_back(acceptor); + } + + // Close all acceptors that are no longer in the configuration file. + for (map::iterator acceptor_it = deserialized_acceptors->begin(); + acceptor_it != deserialized_acceptors->end(); + ++acceptor_it) { + acceptor_it->second->close_socket(); + delete acceptor_it->second; + } + + return acceptors; +} + // Find all streams in the configuration file, and create inputs for them. vector create_inputs(const vector &config, map *deserialized_inputs) @@ -215,13 +262,19 @@ vector create_inputs(const vector &config, if (input->get_url() != src) { fprintf(stderr, "INFO: Stream '%s' has changed URL from '%s' to '%s', restarting input.\n", stream_id.c_str(), input->get_url().c_str(), src.c_str()); + input->close_socket(); delete input; input = NULL; } deserialized_inputs->erase(deserialized_input_it); } if (input == NULL) { - input = new Input(stream_id, src); + input = create_input(stream_id, src); + if (input == NULL) { + fprintf(stderr, "ERROR: did not understand URL '%s', clients will not get any data.\n", + src.c_str()); + continue; + } } input->run(); inputs.push_back(input); @@ -276,7 +329,7 @@ void create_streams(const vector &config, int main(int argc, char **argv) { - fprintf(stderr, "\nCubemap starting.\n"); + fprintf(stderr, "\nCubemap " SERVER_VERSION " starting.\n"); struct timeval serialize_start; bool is_reexec = false; @@ -284,15 +337,14 @@ int main(int argc, char **argv) string config_filename = (argc == 1) ? "cubemap.config" : argv[1]; vector config = parse_config(config_filename); - int port = fetch_config_int(config, "port", 1, 65535, PARAMATER_MANDATORY); int num_servers = fetch_config_int(config, "num_servers", 1, 20000, PARAMATER_MANDATORY); // Insanely high max limit. servers = new ServerPool(num_servers); CubemapStateProto loaded_state; - int server_sock = -1, old_port = -1; set deserialized_stream_ids; map deserialized_inputs; + map deserialized_acceptors; if (argc == 4 && strcmp(argv[2], "-state") == 0) { is_reexec = true; @@ -313,12 +365,22 @@ int main(int argc, char **argv) for (int i = 0; i < loaded_state.inputs_size(); ++i) { deserialized_inputs.insert(make_pair( loaded_state.inputs(i).stream_id(), - new Input(loaded_state.inputs(i)))); + create_input(loaded_state.inputs(i)))); } - // Deserialize the server socket. - server_sock = loaded_state.server_sock(); - old_port = loaded_state.port(); + // Convert the acceptor from older serialized formats. + if (loaded_state.has_server_sock() && loaded_state.has_port()) { + AcceptorProto *acceptor = loaded_state.add_acceptors(); + acceptor->set_server_sock(loaded_state.server_sock()); + acceptor->set_port(loaded_state.port()); + } + + // Deserialize the acceptors. + for (int i = 0; i < loaded_state.acceptors_size(); ++i) { + deserialized_acceptors.insert(make_pair( + loaded_state.acceptors(i).port(), + new Acceptor(loaded_state.acceptors(i)))); + } fprintf(stderr, "done.\n"); } @@ -326,16 +388,6 @@ int main(int argc, char **argv) // Find all streams in the configuration file, and create them. create_streams(config, deserialized_stream_ids, &deserialized_inputs); - // Open a new server socket if we do not already have one, or if we changed ports. - if (server_sock != -1 && port != old_port) { - fprintf(stderr, "NOTE: Port changed from %d to %d; opening new socket.\n", old_port, port); - close(server_sock); - server_sock = -1; - } - if (server_sock == -1) { - server_sock = create_server_socket(port); - } - // See if the user wants stats. string stats_file = fetch_config_string(config, "stats_file", PARAMETER_OPTIONAL); int stats_interval = fetch_config_int(config, "stats_interval", 1, INT_MAX, PARAMETER_OPTIONAL, -1); @@ -345,9 +397,7 @@ int main(int argc, char **argv) servers->run(); - AcceptorThread acceptor_thread(server_sock); - acceptor_thread.run(); - + vector acceptors = create_acceptors(config, &deserialized_acceptors); vector inputs = create_inputs(config, &deserialized_inputs); // All deserialized inputs should now have been taken care of, one way or the other. @@ -392,7 +442,9 @@ int main(int argc, char **argv) if (stats_thread != NULL) { stats_thread->stop(); } - acceptor_thread.stop(); + for (size_t i = 0; i < acceptors.size(); ++i) { + acceptors[i]->stop(); + } for (size_t i = 0; i < inputs.size(); ++i) { inputs[i]->stop(); } @@ -400,7 +452,7 @@ int main(int argc, char **argv) fprintf(stderr, "Serializing state and re-execing...\n"); int state_fd = make_tempfile(collect_state( - serialize_start, server_sock, port, inputs, servers, num_servers)); + serialize_start, acceptors, inputs, servers, num_servers)); delete servers; char buf[16];