<commit_before>/*
 * Copyright 2014 Cloudius Systems
 */

#include "database.hh"
#include "core/app-template.hh"
#include "core/distributed.hh"
#include "thrift/server.hh"
#include "transport/server.hh"
#include "http/httpd.hh"
#include "api/api.hh"
#include "db/config.hh"
#include "service/storage_service.hh"
#include "streaming/stream_session.hh"
#include "db/system_keyspace.hh"
#include "utils/runtime.hh"
#include "dns.hh"
#include "log.hh"
#include "debug.hh"
#include "init.hh"
#include <cstdio>

namespace bpo = boost::program_options;

static future<>
read_config(bpo::variables_map& opts, db::config& cfg) {
    if (opts.count("options-file") == 0) {
        return make_ready_future<>();
    }
    return cfg.read_from_file(opts["options-file"].as<sstring>());
}

static void do_help_loggers() {
    print("Available loggers:\n");
    for (auto&& name : logging::logger_registry().get_all_logger_names()) {
        print("    %s\n", name);
    }
}

static void apply_logger_settings(sstring default_level, db::config::string_map levels,
        bool log_to_stdout, bool log_to_syslog) {
    logging::logger_registry().set_all_loggers_level(boost::lexical_cast<logging::log_level>(std::string(default_level)));
    for (auto&& kv: levels) {
        auto&& k = kv.first;
        auto&& v = kv.second;
        logging::logger_registry().set_logger_level(k, boost::lexical_cast<logging::log_level>(std::string(v)));
    }
    logging::logger::set_stdout_enabled(log_to_stdout);
    logging::logger::set_syslog_enabled(log_to_syslog);
}

int main(int ac, char** av) {
    runtime::init_uptime();
    std::setvbuf(stdout, nullptr, _IOLBF, 1000);
    app_template app;
    auto opt_add = app.add_options();

    auto cfg = make_lw_shared<db::config>();
    bool help_loggers = false;
    cfg->add_options(opt_add)
        ("api-port", bpo::value<uint16_t>()->default_value(10000), "Http Rest API port")
        ("api-dir", bpo::value<sstring>()->default_value("swagger-ui/dist/"),
                "The directory location of the API GUI")
        // TODO : default, always read?
        ("options-file", bpo::value<sstring>(), "cassandra.yaml file to read options from")
        ("help-loggers", bpo::bool_switch(&help_loggers), "print a list of logger names and exit")
        ;

    distributed<database> db;
    debug::db = &db;
    distributed<cql3::query_processor> qp;
    auto& proxy = service::get_storage_proxy();
    api::http_context ctx(db, proxy);

    return app.run(ac, av, [&] {
        if (help_loggers) {
            do_help_loggers();
            engine().exit(1);
            return make_ready_future<>();
        }
        auto&& opts = app.configuration();

        return read_config(opts, *cfg).then([&cfg, &db, &qp, &proxy, &ctx, &opts]() {
            apply_logger_settings(cfg->default_log_level(), cfg->logger_log_level(),
                    cfg->log_to_stdout(), cfg->log_to_syslog());
            dht::set_global_partitioner(cfg->partitioner());
            uint16_t thrift_port = cfg->rpc_port();
            uint16_t cql_port = cfg->native_transport_port();
            uint16_t api_port = opts["api-port"].as<uint16_t>();
            ctx.api_dir = opts["api-dir"].as<sstring>();
            sstring listen_address = cfg->listen_address();
            sstring rpc_address = cfg->rpc_address();
            auto seed_provider= cfg->seed_provider();
            using namespace locator;
            return i_endpoint_snitch::create_snitch(cfg->endpoint_snitch()).then([] {
                engine().at_exit([] { return i_endpoint_snitch::stop_snitch(); });
            }).then([] {
                return service::init_storage_service().then([] {
                    engine().at_exit([] { return service::deinit_storage_service(); });
                });
            }).then([&db, cfg] {
                return db.start(std::move(*cfg)).then([&db] {
                    engine().at_exit([&db] { return db.stop(); });
                });
            }).then([listen_address, seed_provider] {
                return init_ms_fd_gossiper(listen_address, seed_provider);
            }).then([&db] {
                return streaming::stream_session::init_streaming_service(db);
            }).then([&proxy, &db] {
                return proxy.start(std::ref(db)).then([&proxy] {
                    engine().at_exit([&proxy] { return proxy.stop(); });
                });
            }).then([&db, &proxy, &qp] {
                return qp.start(std::ref(proxy), std::ref(db)).then([&qp] {
                    engine().at_exit([&qp] { return qp.stop(); });
                });
            }).then([&db] {
                return parallel_for_each(db.local().get_config().data_file_directories(), [] (sstring datadir) {
                    return recursive_touch_directory(datadir).then_wrapped([datadir] (future<> f) {
                        try {
                            f.get();
                        } catch (std::system_error& e) {
                            fprint(std::cerr, "Directory \"%s\" not found. Tried to created it but failed: %s\n", datadir, e.what());
                            throw;
                        }
                    });
                });
            }).then([&db] {
                return db.invoke_on_all([] (database& db) {
                    return db.init_system_keyspace();
                });
            }).then([&db, &proxy] {
                return db.invoke_on_all([&proxy] (database& db) {
                    return db.load_sstables(proxy);
                });
            }).then([&db, &qp] {
                return db::system_keyspace::setup(db, qp);
            }).then([] {
                auto& ss = service::get_local_storage_service();
                return ss.init_server();
            }).then([rpc_address] {
                return dns::gethostbyname(rpc_address);
            }).then([&db, &proxy, &qp, cql_port, thrift_port] (dns::hostent e) {
                auto rpc_address = e.addresses[0].in.s_addr;
                auto cserver = new distributed<cql_server>;
                cserver->start(std::ref(proxy), std::ref(qp)).then([server = std::move(cserver), cql_port, rpc_address] () mutable {
                    engine().at_exit([server] {
                        return server->stop();
                    });
                    server->invoke_on_all(&cql_server::listen, ipv4_addr{rpc_address, cql_port});
                }).then([cql_port] {
                    std::cout << "CQL server listening on port " << cql_port << " ...\n";
                });
                auto tserver = new distributed<thrift_server>;
                tserver->start(std::ref(db)).then([server = std::move(tserver), thrift_port, rpc_address] () mutable {
                    engine().at_exit([server] {
                        return server->stop();
                    });
                    server->invoke_on_all(&thrift_server::listen, ipv4_addr{rpc_address, thrift_port});
                }).then([thrift_port] {
                    std::cout << "Thrift server listening on port " << thrift_port << " ...\n";
                });
            }).then([&db, api_port, &ctx]{
                ctx.http_server.start().then([api_port, &ctx] {
                    return set_server(ctx);
                }).then([&ctx, api_port] {
                    ctx.http_server.listen(api_port);
                }).then([api_port] {
                    std::cout << "Seastar HTTP server listening on port " << api_port << " ...\n";
                });
            }).or_terminate();
        });
    });
}

namespace debug {

seastar::sharded<database>* db;

}
<commit_msg>main: Introduce api-address option<commit_after>/*
 * Copyright 2014 Cloudius Systems
 */

#include "database.hh"
#include "core/app-template.hh"
#include "core/distributed.hh"
#include "thrift/server.hh"
#include "transport/server.hh"
#include "http/httpd.hh"
#include "api/api.hh"
#include "db/config.hh"
#include "service/storage_service.hh"
#include "streaming/stream_session.hh"
#include "db/system_keyspace.hh"
#include "utils/runtime.hh"
#include "dns.hh"
#include "log.hh"
#include "debug.hh"
#include "init.hh"
#include <cstdio>

namespace bpo = boost::program_options;

static future<>
read_config(bpo::variables_map& opts, db::config& cfg) {
    if (opts.count("options-file") == 0) {
        return make_ready_future<>();
    }
    return cfg.read_from_file(opts["options-file"].as<sstring>());
}

static void do_help_loggers() {
    print("Available loggers:\n");
    for (auto&& name : logging::logger_registry().get_all_logger_names()) {
        print("    %s\n", name);
    }
}

static void apply_logger_settings(sstring default_level, db::config::string_map levels,
        bool log_to_stdout, bool log_to_syslog) {
    logging::logger_registry().set_all_loggers_level(boost::lexical_cast<logging::log_level>(std::string(default_level)));
    for (auto&& kv: levels) {
        auto&& k = kv.first;
        auto&& v = kv.second;
        logging::logger_registry().set_logger_level(k, boost::lexical_cast<logging::log_level>(std::string(v)));
    }
    logging::logger::set_stdout_enabled(log_to_stdout);
    logging::logger::set_syslog_enabled(log_to_syslog);
}

int main(int ac, char** av) {
    runtime::init_uptime();
    std::setvbuf(stdout, nullptr, _IOLBF, 1000);
    app_template app;
    auto opt_add = app.add_options();

    auto cfg = make_lw_shared<db::config>();
    bool help_loggers = false;
    cfg->add_options(opt_add)
        ("api-address", bpo::value<sstring>(), "Http Rest API address")
        ("api-port", bpo::value<uint16_t>()->default_value(10000), "Http Rest API port")
        ("api-dir", bpo::value<sstring>()->default_value("swagger-ui/dist/"),
                "The directory location of the API GUI")
        // TODO : default, always read?
        ("options-file", bpo::value<sstring>(), "cassandra.yaml file to read options from")
        ("help-loggers", bpo::bool_switch(&help_loggers), "print a list of logger names and exit")
        ;

    distributed<database> db;
    debug::db = &db;
    distributed<cql3::query_processor> qp;
    auto& proxy = service::get_storage_proxy();
    api::http_context ctx(db, proxy);

    return app.run(ac, av, [&] {
        if (help_loggers) {
            do_help_loggers();
            engine().exit(1);
            return make_ready_future<>();
        }
        auto&& opts = app.configuration();

        return read_config(opts, *cfg).then([&cfg, &db, &qp, &proxy, &ctx, &opts]() {
            apply_logger_settings(cfg->default_log_level(), cfg->logger_log_level(),
                    cfg->log_to_stdout(), cfg->log_to_syslog());
            dht::set_global_partitioner(cfg->partitioner());
            uint16_t thrift_port = cfg->rpc_port();
            uint16_t cql_port = cfg->native_transport_port();
            uint16_t api_port = opts["api-port"].as<uint16_t>();
            ctx.api_dir = opts["api-dir"].as<sstring>();
            sstring listen_address = cfg->listen_address();
            sstring rpc_address = cfg->rpc_address();
            sstring api_address = opts.count("api-address") ? opts["api-address"].as<sstring>() : rpc_address;
            auto seed_provider= cfg->seed_provider();
            using namespace locator;
            return i_endpoint_snitch::create_snitch(cfg->endpoint_snitch()).then([] {
                engine().at_exit([] { return i_endpoint_snitch::stop_snitch(); });
            }).then([] {
                return service::init_storage_service().then([] {
                    engine().at_exit([] { return service::deinit_storage_service(); });
                });
            }).then([&db, cfg] {
                return db.start(std::move(*cfg)).then([&db] {
                    engine().at_exit([&db] { return db.stop(); });
                });
            }).then([listen_address, seed_provider] {
                return init_ms_fd_gossiper(listen_address, seed_provider);
            }).then([&db] {
                return streaming::stream_session::init_streaming_service(db);
            }).then([&proxy, &db] {
                return proxy.start(std::ref(db)).then([&proxy] {
                    engine().at_exit([&proxy] { return proxy.stop(); });
                });
            }).then([&db, &proxy, &qp] {
                return qp.start(std::ref(proxy), std::ref(db)).then([&qp] {
                    engine().at_exit([&qp] { return qp.stop(); });
                });
            }).then([&db] {
                return parallel_for_each(db.local().get_config().data_file_directories(), [] (sstring datadir) {
                    return recursive_touch_directory(datadir).then_wrapped([datadir] (future<> f) {
                        try {
                            f.get();
                        } catch (std::system_error& e) {
                            fprint(std::cerr, "Directory \"%s\" not found. Tried to created it but failed: %s\n", datadir, e.what());
                            throw;
                        }
                    });
                });
            }).then([&db] {
                return db.invoke_on_all([] (database& db) {
                    return db.init_system_keyspace();
                });
            }).then([&db, &proxy] {
                return db.invoke_on_all([&proxy] (database& db) {
                    return db.load_sstables(proxy);
                });
            }).then([&db, &qp] {
                return db::system_keyspace::setup(db, qp);
            }).then([] {
                auto& ss = service::get_local_storage_service();
                return ss.init_server();
            }).then([rpc_address] {
                return dns::gethostbyname(rpc_address);
            }).then([&db, &proxy, &qp, cql_port, thrift_port] (dns::hostent e) {
                auto rpc_address = e.addresses[0].in.s_addr;
                auto cserver = new distributed<cql_server>;
                cserver->start(std::ref(proxy), std::ref(qp)).then([server = std::move(cserver), cql_port, rpc_address] () mutable {
                    engine().at_exit([server] {
                        return server->stop();
                    });
                    server->invoke_on_all(&cql_server::listen, ipv4_addr{rpc_address, cql_port});
                }).then([cql_port] {
                    std::cout << "CQL server listening on port " << cql_port << " ...\n";
                });
                auto tserver = new distributed<thrift_server>;
                tserver->start(std::ref(db)).then([server = std::move(tserver), thrift_port, rpc_address] () mutable {
                    engine().at_exit([server] {
                        return server->stop();
                    });
                    server->invoke_on_all(&thrift_server::listen, ipv4_addr{rpc_address, thrift_port});
                }).then([thrift_port] {
                    std::cout << "Thrift server listening on port " << thrift_port << " ...\n";
                });
            }).then([api_address] {
                return dns::gethostbyname(api_address);
            }).then([&db, api_address, api_port, &ctx] (dns::hostent e){
                auto ip = e.addresses[0].in.s_addr;
                ctx.http_server.start().then([api_address, api_port, ip, &ctx] {
                    return set_server(ctx);
                }).then([api_address, api_port, ip, &ctx] {
                    ctx.http_server.listen(ipv4_addr{ip, api_port});
                }).then([api_address, api_port] {
                    print("Seastar HTTP server listening on %s:%s ...\n", api_address, api_port);
                });
            }).or_terminate();
        });
    });
}

namespace debug {

seastar::sharded<database>* db;

}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <string.h>
#include <cstring>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
using namespace std;

int main(){

    string COLON = ";";
    string PIPE = "||";
    string AND = "&&";

    char HOSTNAME[128];
    gethostname(HOSTNAME, sizeof HOSTNAME);

    while (1){
        string i;
        cout << getlogin() << "@" << HOSTNAME << "$ ";
        getline(cin, i);

        string w = "";
        vector <string> word;
        vector< vector<string> > comm;
        bool quote = false;

        for (unsigned j = 0; j < i.size(); ++j){
            if (j == i.size() - 1){
                if(i.at(j)!='\"') w.push_back(i.at(j));
                word.push_back(w);
                comm.push_back(word);
            }
            else{
                if (quote){ //In quotes
                   // if ((i.at(j) == '\"' && i.at(j - 1) != '\\') || j == i.size() - 1){
                    if(i.at(j) == '\"' && i.at(j-1) != '\\'){
                       // w.push_back(i.at(j));
                        word.push_back(w);
                        w.clear();
                        quote = !quote;
                    }
                    else{
                        w.push_back(i.at(j));
                    }
                }
                else{ //Not in quotes
                    if (i.at(j) == '\"'){
                        quote = !quote;
                        j++;
                        w.push_back(i.at(j));
                    }
                    else if (i.at(j) == ';'){
                        word.push_back(w);
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        word.push_back(COLON);
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                    }
                    else if ((i.at(j) == '&' && i.at(j + 1) == '&')){
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        word.push_back(AND);
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        j+=1;
                    }
                    else if ((i.at(j) == '|' && i.at(j + 1) == '|')){
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        word.push_back(PIPE);
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        j+=1;
                    }
                    else if (i.at(j) == ' '){
                        if (!(w.empty())){
                            word.push_back(w);
                            w.clear();
                        }
                    }
                    else if (i.at(j) == '#'){
                        if (!(w.empty())){
                            word.push_back(w);
                        }
                        break;
                    }
                    else{
                        w.push_back(i.at(j));
                    }
                }
            }
        }

        // for (unsigned l = 0; l < comm.size(); ++l){
        //     for (unsigned m = 0; m < comm.at(l).size(); ++m){
        //         cout << comm.at(l).at(m) << " ";
        //     }
        //     cout << endl;
        // }

        bool didItExecute = true;
        bool shouldItExecute = true;

        for (unsigned first = 0; first < comm.size(); first++){
            for (unsigned second = 0; second < comm.at(first).size(); second++){
                if (comm.at(first).at(second) == "exit"){
                    exit(0);
                }
            }
        }

        for (unsigned j = 0; j < comm.size(); ++j){
            if (comm.at(j).size() == 1 && comm.at(j).at(0) == ";"){
                shouldItExecute = true;
            }

            else if (comm.at(j).size() == 1 && comm.at(j).at(0) == "||"){
                if (didItExecute){
                    shouldItExecute = false;
                }
                else{
                    shouldItExecute = true;
                }
            }

            else if (comm.at(j).size() == 1 && comm.at(j).at(0) == "&&"){
                if (didItExecute){
                    shouldItExecute = true;
                }
                else{
                    shouldItExecute = false;
                }
            }

            else{
                unsigned size = comm.at(j).size() + 1;
                char**args = new char*[size];

                for (unsigned i = 0; i < size - 1; ++i){
                    const char *mystr = comm.at(j).at(i).c_str();
                    args[i] = const_cast<char *> (&mystr[0]);
                }

                args[size - 1] = 0;

                if (shouldItExecute){
                    int status;
                    pid_t c_pid, pid; // Where c_pid is child
                    c_pid = fork();
                    if (c_pid < 0)
                    {
                        perror("fork failed");
                        exit(1);
                    }
                    else if (c_pid == 0) // Child process
                    {
                        execvp(args[0], args);
                        perror("-bash");
                        exit(1);
                    }
                    else if (c_pid > 0)
                    {
                        if ( (pid = wait(&status)) < 0)
                        {
                            perror("wait");
                            exit(1);
                        }

                        if (WEXITSTATUS(status) != 0){
                            didItExecute = false;
                        }
                        else{
                            didItExecute = true;
                        }
                        delete [] args;
                    }
                }
            }
        }
    }
    return 0;
}
<commit_msg>added comments<commit_after>#include <iostream>
#include <vector>
#include <string.h>
#include <cstring>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
using namespace std;

int main(){

    string COLON = ";";
    string PIPE = "||";
    string AND = "&&";

    char HOSTNAME[128];
    gethostname(HOSTNAME, sizeof HOSTNAME);

    //Loop will only break if the user enters 'exit' in the inputted command.
    while (1){
        string i;
        cout << getlogin() << "@" << HOSTNAME << "$ ";
        getline(cin, i);
        string w = "";
        vector <string> word; //This will an individual command after parsing.
        vector< vector<string> > comm; //After parsing this will hold commands in the order they were inputed.
        bool quote = false;

        /* This for loop will iterate through the inputed string and separate commands
           by the connectors. When a connector is found vector word which holds a
           single command will be pushed back into vector comm which will eventually
           hold all the concatenated commands. After word is pushed back, the
           appropriate connector will be pushed into comm as well.
        */
        for (unsigned j = 0; j < i.size(); ++j){
            //If the end is reached pushes data into comm.
            if (j == i.size() - 1){
                if(i.at(j)!='\"') w.push_back(i.at(j));
                word.push_back(w);
                comm.push_back(word);
            }
            else{
                if (quote){ //In quotes
                   // if ((i.at(j) == '\"' && i.at(j - 1) != '\\') || j == i.size() - 1){
                    if(i.at(j) == '\"' && i.at(j-1) != '\\'){
                       // w.push_back(i.at(j));
                        word.push_back(w);
                        w.clear();
                        quote = !quote;
                    }
                    else{
                        w.push_back(i.at(j));
                    }
                }
                else{ //Not in quotes
                    if (i.at(j) == '\"'){
                        quote = !quote;
                        j++;
                        w.push_back(i.at(j));
                    }
                    //If semicolon is found push created vector into com.
                    else if (i.at(j) == ';'){
                        word.push_back(w);
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        word.push_back(COLON);
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                    }
                    //If && is found push created vector into com.
                    else if ((i.at(j) == '&' && i.at(j + 1) == '&')){
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        word.push_back(AND);
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        j+=1;
                    }
                    //If || is found push created vector into com.
                    else if ((i.at(j) == '|' && i.at(j + 1) == '|')){
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        word.push_back(PIPE);
                        comm.push_back(word);
                        word.clear();
                        w.clear();
                        j+=1;
                    }
                    //If a space is found push created word into word.
                    else if (i.at(j) == ' '){
                        if (!(w.empty())){
                            word.push_back(w);
                            w.clear();
                        }
                    }
                    //If a # is found outside of quotes, stops parsing process and
                    //begins execution.
                    else if (i.at(j) == '#'){
                        if (!(w.empty())){
                            word.push_back(w);
                        }
                        break;
                    }
                    else{
                        w.push_back(i.at(j));
                    }
                }
            }
        }

        bool didItExecute = true; //Checks if the current command executed or not.
        bool shouldItExecute = true; //Determines if the current command should execute or not.

        //Commands are executed here.
        for (unsigned j = 0; j < comm.size(); ++j){
            //If command is exit, execution is stopped and outer while loop restarts.
            if (comm.at(j).size() == 1 && comm.at(j).at(0) == "exit"){
                exit(0);
            }
            //If a semicolon is found, automatically set shouldItExecute to true
            //so next command will execute.
            else if (comm.at(j).size() == 1 && comm.at(j).at(0) == ";"){
                shouldItExecute = true;
            }
            //If || is found checks didItExecute to see if previous command executed.
            //If it did it will set shouldItExecute to false, true otherwise.
            else if (comm.at(j).size() == 1 && comm.at(j).at(0) == "||"){
                if (didItExecute){
                    shouldItExecute = false;
                }
                else{
                    shouldItExecute = true;
                }
            }
            //If && is found checks didItExecute to see if previous command executed.
            //If it did it will set shouldItExecute to true, false otherwise.
            else if (comm.at(j).size() == 1 && comm.at(j).at(0) == "&&"){
                if (didItExecute){
                    shouldItExecute = true;
                }
                else{
                    shouldItExecute = false;
                }
            }
            else{
                unsigned size = comm.at(j).size() + 1;
                char**args = new char*[size]; //Creates args of type char** which will be inputed to execvp.
                args[size - 1] = 0;
                //stores each command in comm into char to beable to be executed.
                for (unsigned i = 0; i < size - 1; ++i){
                    const char *mystr = comm.at(j).at(i).c_str();
                    args[i] = const_cast<char *> (&mystr[0]);
                }
                //If shouldItExecute is true, which would be set by the connectors
                //above, then the current command is executed.
                if (shouldItExecute){
                    int status;
                    pid_t pid;
                    pid = fork(); //Forks a child process.
                    if (pid < 0) //Fork failed, exits program.
                    {
                        perror("Fork Failed");
                        exit(1);
                    }
                    else if (pid == 0) //Fork is successful.
                    {
                        if (execvp(args[0], args) < 0){ //executes the command.
                            perror("-bash"); //Execution failed if it takes this branch.
                            didItExecute = false; //Update execution information for following commands.
                        }
                        else{
                            didItExecute = true; //Execution successful. Updates execution info.
                        }
                    }
                    else
                    {   //Makes the parent wait until child process completes.
                        while ( wait(&status) != pid)
                        {
                            perror("wait");
                        }
                        didItExecute = true;
                        delete [] args;
                    }
                }
            }
        }
    }
    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include "Feeder.h"
#include "Environment.h"
#include "Script.h"
#include <fstream>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
using namespace std;

int scriptPos(int argc, char const* argv[]);
void parseErrorMsg(Element *e);
void execErrorMsg(Element *e);
void setFlags(int argc, char const* argv[],Environment *e);

static void sig_int(int sig)
{
	Element::m_signal = sig;
}

int main(int argc, char const* argv[])
{
	if(argc <= 1)
		exit(0);

///////////////////////////////////////////
// set signals
//////////////////////////////////////////
	struct sigaction sig;
	memset(&sig,'\0',sizeof(sig));

	sig.sa_handler = sig_int;
	sigaction(SIGINT,&sig,NULL);

///////////////////////////////////////////
// initialization of top level objects
//////////////////////////////////////////
	int script_pos = scriptPos(argc,argv);
	ifstream ifs(argv[script_pos]);
	Feeder feeder(&ifs);
	Environment env(argc,argv,script_pos);

	// set tmpdir
	string tmp_k = "tmpdir";
	string tmp_v = "/tmp/";
	env.setImportPath(&tmp_k,&tmp_v);
	Script s(&feeder,&env);

	setFlags(argc,argv,&env);
///////////////////////////////////////////
// parse
//////////////////////////////////////////
	try{
		s.parse();
	}
	catch(Element *e){
		parseErrorMsg(e);
		env.removeFiles();
		exit(e->getExitStatus());
	}
	catch(...){
		cerr << "\nParse error" << endl;
		cerr << "unknown error" << endl;
		env.removeFiles();
		exit(1);
	}

///////////////////////////////////////////
// exec
//////////////////////////////////////////
	try{
		int status = s.exec();
		env.removeFiles();

		if(status == 0)
			exit(0);
	}
	catch(Element *e){
		execErrorMsg(e);
		env.removeFiles();
		int es = e->getExitStatus();
		if(es == 127)
			_exit(es);
		else
			exit(es);
	}
	catch(...){
		cerr << "\nExecution error" << endl;
		cerr << "unknown error" << endl;
		env.removeFiles();
		exit(1);
	}

	cerr << "unknown error (uncatched)" << endl;
	env.removeFiles();
	exit(1);
}

int scriptPos(int argc, char const* argv[])
{
	string com = string(argv[0]);
	bool shebang = com.substr(com.find_last_of('/') + 1) != "glue";

	if(shebang)
		return 0;

	int i=1;
	for(;i<argc;i++){
		if(argv[i][0] != '-')
			break;
	}
	return i;
}

void parseErrorMsg(Element *e)
{
	cerr << "\nParse error at " ;
	cerr << e->pos() << endl;
	e->printErrorPart();
	cerr << "\n\t" << e->m_error_msg << endl;
	cerr << "\t";

	cerr << '\n';
	cerr <<  "\tprocess_level " << e->getLevel() << endl;
	cerr << "\texit_status " << e->getExitStatus() << endl;
	cerr << "\tpid " << getpid() << '\n' << endl;
}

void execErrorMsg(Element *e)
{
	cerr << "\nExecution error at " ;
	cerr << e->pos() << endl;
	e->printErrorPart();
	cerr << "\n\t" << e->m_error_msg << endl;
	cerr << "\t\n";
	cerr <<  "\tprocess_level " << e->getLevel() << endl;
	cerr << "\texit_status " << e->getExitStatus() << endl;
	cerr << "\tpid " << getpid() << '\n' << endl;
}

void setFlags(int argc, char const* argv[],Environment *e)
{
	int result = 0;
	while((result = getopt(argc,(char**)argv,"v"))!=-1){
		switch(result){
		case 'v':
			e->m_v_opt = true;
			break;
		}
	}

}
<commit_msg>Add usage<commit_after>#include <iostream>
#include "Feeder.h"
#include "Environment.h"
#include "Script.h"
#include <fstream>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
using namespace std;

int scriptPos(int argc, char const* argv[]);
void parseErrorMsg(Element *e);
void execErrorMsg(Element *e);
bool setFlags(int argc, char const* argv[],Environment *e);

static void sig_int(int sig)
{
	Element::m_signal = sig;
}

int main(int argc, char const* argv[])
{
	if(argc <= 1)
		exit(0);

///////////////////////////////////////////
// set signals
//////////////////////////////////////////
	struct sigaction sig;
	memset(&sig,'\0',sizeof(sig));

	sig.sa_handler = sig_int;
	sigaction(SIGINT,&sig,NULL);

///////////////////////////////////////////
// initialization of top level objects
//////////////////////////////////////////
	int script_pos = scriptPos(argc,argv);

	ifstream ifs(argv[script_pos]);
	Feeder feeder(&ifs);
	Environment env(argc,argv,script_pos);

	if(!setFlags(argc,argv,&env))
		exit(1);

	// set tmpdir
	string tmp_k = "tmpdir";
	string tmp_v = "/tmp/";
	env.setImportPath(&tmp_k,&tmp_v);
	Script s(&feeder,&env);

///////////////////////////////////////////
// parse
//////////////////////////////////////////
	try{
		s.parse();
	}
	catch(Element *e){
		parseErrorMsg(e);
		env.removeFiles();
		exit(e->getExitStatus());
	}
	catch(...){
		cerr << "\nParse error" << endl;
		cerr << "unknown error" << endl;
		env.removeFiles();
		exit(1);
	}

///////////////////////////////////////////
// exec
//////////////////////////////////////////
	try{
		int status = s.exec();
		env.removeFiles();

		if(status == 0)
			exit(0);
	}
	catch(Element *e){
		execErrorMsg(e);
		env.removeFiles();
		int es = e->getExitStatus();
		if(es == 127)
			_exit(es);
		else
			exit(es);
	}
	catch(...){
		cerr << "\nExecution error" << endl;
		cerr << "unknown error" << endl;
		env.removeFiles();
		exit(1);
	}

	cerr << "unknown error (uncatched)" << endl;
	env.removeFiles();
	exit(1);
}

int scriptPos(int argc, char const* argv[])
{
	string com = string(argv[0]);
	bool shebang = com.substr(com.find_last_of('/') + 1) != "glue";

	if(shebang)
		return 0;

	int i=1;
	for(;i<argc;i++){
		if(argv[i][0] != '-')
			break;
	}
	return i;
}

void parseErrorMsg(Element *e)
{
	cerr << "\nParse error at " ;
	cerr << e->pos() << endl;
	e->printErrorPart();
	cerr << "\n\t" << e->m_error_msg << endl;
	cerr << "\t";

	cerr << '\n';
	cerr <<  "\tprocess_level " << e->getLevel() << endl;
	cerr << "\texit_status " << e->getExitStatus() << endl;
	cerr << "\tpid " << getpid() << '\n' << endl;
}

void execErrorMsg(Element *e)
{
	cerr << "\nExecution error at " ;
	cerr << e->pos() << endl;
	e->printErrorPart();
	cerr << "\n\t" << e->m_error_msg << endl;
	cerr << "\t\n";
	cerr <<  "\tprocess_level " << e->getLevel() << endl;
	cerr << "\texit_status " << e->getExitStatus() << endl;
	cerr << "\tpid " << getpid() << '\n' << endl;
}

void usage(void)
{
	cerr << "GlueLang (master branch)" << endl;
	cerr << "Usage: glue [OPTION] [FILE]" << endl;
	cerr << endl;
	cerr << "Copyright (C) 2015 Ryuichi Ueda" << endl;
	cerr << "GlueLang repo. <https://github.com/ryuichiueda/GlueLang>" << endl;
}

bool setFlags(int argc, char const* argv[],Environment *e)
{
	struct option long_opts[] = {
		{"help",0,NULL,'h'},
		{"usage",0,NULL,'h'},
		{"verbose",0,NULL,'v'},
		{0,0,0,0}
	};

	int opt = 0;
	int idx = 0;
	while((opt = getopt_long(argc,(char *const *)argv,"hv",long_opts,&idx)) != -1){
		switch (opt){
		case 'h':
			usage();
			return false;
		case 'v':
			e->m_v_opt = true;
			break;
		}
	}
	return true;
}
<|endoftext|>


<commit_before>/*
 * wheel.cpp
 *
 *  Created on: Sep 2, 2014
 *      Author: posborne
 */

#include <functional>
#include "wheel.h"

// TODO: only necessary as mbed does not allow for passing a data pointer
// along with interrupt registrations.  Obviously, this breaks if we ever
// have more than one wheel sensor created.
static BicycleWheel* g_wheel; /* global wheel reference */

/*
 * ISR called when we receive an rising edge on the reed sensor
 */
static void reedSwitchRisingInterrupt()
{
    if (g_wheel != NULL) {
        g_wheel->onRisingInterrupt();
    }
}

/*
 * ISR called when we receive an falling edge on the reed sensor
 */
static void reedSwitchFallingInterrupt()
{
    if (g_wheel != NULL) {
        g_wheel->onFallingInterrupt();
    }
}

BicycleWheel::BicycleWheel(PinName reedSwitchPin, DebugSerialPort& debugSerialPort, MulticolorLED& debugLED) :
    m_reedSwitchPin(reedSwitchPin),
    m_reedSwitchGPIO(m_reedSwitchPin),
    m_reedSwitchInterrupt(m_reedSwitchPin),
    m_debugSerialPort(debugSerialPort),
    m_led(debugLED)
{
    g_wheel = this;
}

BicycleWheel::~BicycleWheel()
{
    g_wheel = NULL;
}

void BicycleWheel::init()
{
    m_led.show(0.0, 0.0, 0.0);
    m_reedSwitchInterrupt.rise(reedSwitchRisingInterrupt);
    m_reedSwitchInterrupt.fall(reedSwitchFallingInterrupt);
}

void BicycleWheel::onFallingInterrupt()
{
    m_debugSerialPort.writeln("Reed Switch Rising Edge");
    m_led.show(0, 0, 0.05); // subtle blue
}

void BicycleWheel::onRisingInterrupt()
{
    m_debugSerialPort.writeln("Reed Switch Falling Edge");
    m_led.show(0.01, 0.05, 0.0); // subtle yellow
}
<commit_msg>transistor: temporary hack using transistor as switch to emulate reed switch<commit_after>/*
 * wheel.cpp
 *
 *  Created on: Sep 2, 2014
 *      Author: posborne
 */

#include <functional>
#include "wheel.h"

static DigitalOut tpin(PTD4);

// TODO: only necessary as mbed does not allow for passing a data pointer
// along with interrupt registrations.  Obviously, this breaks if we ever
// have more than one wheel sensor created.
static BicycleWheel* g_wheel; /* global wheel reference */

/*
 * ISR called when we receive an rising edge on the reed sensor
 */
static void reedSwitchRisingInterrupt()
{
    if (g_wheel != NULL) {
        g_wheel->onRisingInterrupt();
    }
}

/*
 * ISR called when we receive an falling edge on the reed sensor
 */
static void reedSwitchFallingInterrupt()
{
    if (g_wheel != NULL) {
        g_wheel->onFallingInterrupt();
    }
}

BicycleWheel::BicycleWheel(PinName reedSwitchPin, DebugSerialPort& debugSerialPort, MulticolorLED& debugLED) :
    m_reedSwitchPin(reedSwitchPin),
    m_reedSwitchGPIO(m_reedSwitchPin),
    m_reedSwitchInterrupt(m_reedSwitchPin),
    m_debugSerialPort(debugSerialPort),
    m_led(debugLED)
{
    g_wheel = this;
}

BicycleWheel::~BicycleWheel()
{
    g_wheel = NULL;
}

void BicycleWheel::init()
{
    m_led.show(0.0, 0.0, 0.0);
    m_reedSwitchInterrupt.rise(reedSwitchRisingInterrupt);
    m_reedSwitchInterrupt.fall(reedSwitchFallingInterrupt);
}

void BicycleWheel::onFallingInterrupt()
{
    tpin = 0;
    m_debugSerialPort.writeln("Reed Switch Rising Edge");
    m_led.show(0, 0, 0.05); // subtle blue
}

void BicycleWheel::onRisingInterrupt()
{
    tpin = 1;
    m_debugSerialPort.writeln("Reed Switch Falling Edge");
    m_led.show(0.01, 0.05, 0.0); // subtle yellow
}
<|endoftext|>


<commit_before>#include <algorithm>
#include <experimental/string_view>
#include <unordered_map>
#include <vector>

#include <fcntl.h>
#include <netdb.h>
#include <netinet/tcp.h>

#include <sys/stat.h>
#include <unistd.h>

#include "core/yta_event_loop.h"
#include "http/yta_http.hpp"

#include "args.h"
#include "picohttpparser/picohttpparser.h"

const std::size_t MAX_URL_SIXE = 512;
const std::size_t MAX_HEADERS = 20;
const std::size_t MAX_BUFFER_SIZE = 1024;

typedef unsigned char byte;

struct parser_data {
    const char* method = nullptr;
    std::size_t method_len = 0;
    const char* path = nullptr;
    std::size_t path_len = 0;
    int pret = 0;
    int minor_version = 0;
    std::array<phr_header, MAX_HEADERS> headers;
    std::size_t num_headers = MAX_HEADERS;
};

struct user_data {
    std::size_t counter;

    std::array<char, MAX_BUFFER_SIZE> buf;
    std::array<char, MAX_BUFFER_SIZE> response_buf;

    bool finalized;

    std::size_t response_size;
    bool content;
    std::experimental::string_view extension;

    int file_fd;
    std::size_t file_size;
    std::size_t offset = 0;

    parser_data parser;

    struct stat file_stat;
};

void return_400(user_data* udata) {
    auto ret = yta::http::serve_400(udata->response_buf.data());
    udata->response_size = ret - udata->response_buf.data();
    udata->content = false;
    udata->finalized = true;
}

void return_404(user_data* udata) {
    auto ret = yta::http::serve_404(udata->response_buf.data());
    udata->response_size = ret - udata->response_buf.data();
    udata->content = false;
    udata->finalized = true;
}

std::unordered_map<std::experimental::string_view, std::experimental::string_view>
    mime_types{ { ".html", "text/html" },
                { ".css", "text/css" },
                { ".png", "image/png" },
                { ".jpg", "image/jpeg" },
                { ".jpeg", "image/jpeg" },
                { ".txt", "text/plain" },
                { ".js", "application/x-javascript" },
                { ".json", "application/json" },
                { ".pdf", "application/pdf" },
                { ".zip", "application/zip" },
                { ".woff", "application/font-woff" },
                { ".woff2", "application/font-woff2" },
                { ".opus", "audio/opus" },
                { ".mp4", "video/mp4" },
                { ".mpeg", "video/mpeg" },
                { ".mpg", "video/mpeg" },
                { ".mp3", "audio/mpeg" } };

int parse_url(yta_ctx* ctx, const char* path, size_t length) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    // parse query string
    auto pos = std::find(path, path + length, '?');
    if (pos != path + length) {
        length = pos - path;
    }

    // clean path buffer is MAX_URL_SICE
    // leave space for appended index.html
    if ((length > (MAX_URL_SIXE - 20)) || (length == 0)) {
        return_404(udata);
        return 0;
    }

    char normalized_path[MAX_URL_SIXE] = { 0 };
    // prepend . for current directory
    normalized_path[0] = '.';
    std::size_t new_length = 1;

    // clean path
    new_length += yta::http::clean_path(path, length, normalized_path + 1);

    // clean_path removes trailing slash except for root;
    // put the trailing slash back if necessary.
    if (path[length - 1] == '/' && new_length != 2) {
        normalized_path[new_length] = '/';
        ++new_length;
    }

    // append index.html to urls with trailing slashes
    if (normalized_path[new_length - 1] == '/') {
        const char index_html[] = "index.html";
        std::copy(std::begin(index_html), std::end(index_html),
                  normalized_path + new_length);
        new_length += 10;
    }

    int ffd = open(normalized_path, O_RDONLY);

    if (ffd == -1) {
        return_404(udata);
        return 0;
    }

    struct stat file_stat;
    int status = fstat(ffd, &file_stat);

    if (status != 0 || !S_ISREG(file_stat.st_mode)) {
        return_404(udata);
        close(ffd);
        return 0;
    }

    std::experimental::string_view path_view(normalized_path, new_length);
    auto filetype_begin = path_view.rfind('.');
    auto file_begin = path_view.rfind('/');

    // we always find . at the beginning because of ./FILENAME
    if (file_begin < filetype_begin) {
        auto it = mime_types.find(path_view.substr(filetype_begin));
        if (it != mime_types.end()) {
            udata->extension = it->second;
        } else {
            udata->extension = { "text/plain" };
        }
    } else {
        udata->extension = { "text/plain" };
    }

    udata->file_fd = ffd;
    udata->file_size = file_stat.st_size;
    udata->file_stat = file_stat;

    return 0;
}

typedef bool (*header_handler)(yta_ctx*, std::experimental::string_view);

bool handle_if_modified_since(yta_ctx* ctx, std::experimental::string_view value) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    tm stamp;
    if (strptime(value.data(), yta::http::http_time_format(), &stamp) == NULL) {
        auto end = yta::http::serve_400(udata->response_buf.data());
        udata->response_size = end - udata->response_buf.data();
        udata->content = false;
        udata->finalized = true;
        return true;
    }
    time_t time = timegm(&stamp);

    // not modified
    if (time >= udata->file_stat.st_mtime) {
        auto end = yta::http::serve_304(udata->response_buf.data());
        udata->response_size = end - udata->response_buf.data();
        udata->content = false;
        udata->finalized = true;
        return true;
    }

    return false;
}

bool handle_range(yta_ctx* ctx, std::experimental::string_view value) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    // 7 bytes=X-
    if (value.size() < 8) {
        return_400(udata);
        return true;
    }

    auto iter = value.begin();

    if (!std::equal(iter, iter + 6, "bytes=")) {
        return_400(udata);
        return true;
    }

    std::advance(iter, 6);

    auto sep = std::find(iter, value.end(), '-');

    if (sep == value.end()) {
        return_400(udata);
        return true;
    }

    // Range: bytes=-123
    if (sep == iter) {
        // this should be supported by rfc
        return_400(udata);
        return true;
    }

    // TODO: think of something smarter to not create temp std::string
    // boost::lexical_cast would work
    auto val = std::string(iter, sep);
    int start_value = std::stoi(val);
    int end_value = 0;

    if (std::next(sep, 1) == value.end()) { // Range: bytes=123-
        end_value = udata->file_stat.st_size - 1;
    } else { // Range: bytes=123-200
        auto val = std::string(sep + 1, value.end());
        end_value = std::stoi(val);
    }

    // sanity checks
    if (end_value <= start_value) {
        end_value = udata->file_stat.st_size - 1;
    }

    if (start_value < 0) {
        start_value = 0;
    }

    if (end_value >= udata->file_stat.st_size) {
        end_value = udata->file_stat.st_size - 1;
    }

    udata->file_size = end_value - start_value + 1;
    udata->offset = start_value;

    auto end = yta::http::serve_206(udata->response_buf.data(), udata->file_size,
                                    &udata->file_stat.st_mtime, start_value, end_value,
                                    udata->file_stat.st_size);
    udata->response_size = end - udata->response_buf.data();
    udata->content = true;
    udata->finalized = true;

    return true;
}

std::unordered_map<std::experimental::string_view, header_handler> header_callbacks{
    { "If-Modified-Since", handle_if_modified_since }, { "Range", handle_range }
};

int parse_headers(yta_ctx* ctx) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    for (std::size_t i = 0; (i < udata->parser.num_headers) && !udata->finalized; ++i) {
        std::experimental::string_view header(udata->parser.headers[i].name,
                                              udata->parser.headers[i].name_len);
        auto it = header_callbacks.find(header);
        if (it != header_callbacks.end()) {
            std::experimental::string_view value(udata->parser.headers[i].value,
                                                 udata->parser.headers[i].value_len);
            auto done = it->second(ctx, value);
            if (done) {
                return 0;
            }
        }
    }

    if (!udata->finalized) {
        auto end = yta::http::serve_200(udata->response_buf.data(), udata->file_size,
                                        &udata->file_stat.st_mtime, udata->extension);
        udata->response_size = end - udata->response_buf.data();
        udata->content = true;
        udata->finalized = true;
    }
    return 0;
}

void accept_logic(yta_ctx* ctx, user_data* udata);

yta_callback_status http_finish_callback(yta_ctx* ctx, void*, size_t) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    if (udata->file_fd != 0) {
        close(udata->file_fd);
        udata->file_fd = 0;
    }

    // uncork
    int enable = 0;
    if (setsockopt(ctx->fd, IPPROTO_TCP, TCP_CORK, &enable, sizeof(enable)) < 0) {
        fprintf(stderr, "error setting TCP_CORK");
        exit(1);
    }

    accept_logic(ctx, udata);
    return YTA_OK;
}

yta_callback_status write_header_callback(yta_ctx* ctx, void*, size_t) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);
    if (udata->content) {
        yta_async_sendfile(ctx, http_finish_callback, udata->file_fd, udata->file_size,
                           udata->offset);
        return YTA_OK;
    } else {
        return http_finish_callback(ctx, NULL, 0);
    }
}

yta_callback_status read_callback_http(yta_ctx* ctx, void* buf, size_t read) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    std::size_t prev_count = udata->counter;
    udata->counter += read;

    int parsed = phr_parse_request(
        udata->buf.data(), udata->counter, &udata->parser.method,
        &udata->parser.method_len, &udata->parser.path, &udata->parser.path_len,
        &udata->parser.minor_version, udata->parser.headers.data(),
        &udata->parser.num_headers, prev_count);

    if (parsed == -1) {
        return_400(udata);
    } else if (parsed > 0) {
        parse_url(ctx, udata->parser.path, udata->parser.path_len);
        parse_headers(ctx);
    }

    if (udata->finalized) {
        // cork
        int enable = 1;
        if (setsockopt(ctx->fd, IPPROTO_TCP, TCP_CORK, &enable, sizeof(enable)) < 0) {
            fprintf(stderr, "error setting TCP_CORK");
            exit(1);
        }

        yta_async_write(ctx, write_header_callback, udata->response_buf.data(),
                        udata->response_size);
        return YTA_OK;
    }

    if (udata->counter == MAX_BUFFER_SIZE) {
        return http_finish_callback(ctx, NULL, 0);
    }

    yta_async_read(ctx, read_callback_http, (char*)buf + read,
                   MAX_BUFFER_SIZE - udata->counter);
    return YTA_OK;
}

yta_callback_status http_cleanup(yta_ctx* ctx) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    if (udata->file_fd != 0) {
        close(udata->file_fd);
        udata->file_fd = 0;
    }

    delete udata;

    return YTA_EXIT;
}

yta_callback_status timer_callback(yta_ctx* /* ctx */) {
    printf("Force closing http connection\n");
    return YTA_EXIT;
}

void accept_logic(yta_ctx* ctx, user_data* udata) {
    udata->parser = parser_data{};
    udata->counter = 0;
    udata->finalized = false;
    udata->file_fd = 0;
    yta_async_read(ctx, read_callback_http, udata->buf.data(), MAX_BUFFER_SIZE);
}

yta_callback_status accept_callback_http(yta_ctx* ctx) {
    user_data* udata = new user_data;
    if (udata == nullptr) {
        return YTA_EXIT;
    }
    ctx->user_data = udata;
    yta_set_close_callback(ctx, http_cleanup);
    yta_async_timer(ctx, timer_callback, 300, 0);
    accept_logic(ctx, udata);
    return YTA_OK;
}

int main(int argc, char** argv) {
    auto opts = get_program_opts(argc, argv);

    yta_run(argv, opts.host.c_str(), opts.port.c_str(), opts.pid_file.c_str(),
            opts.daemonize, opts.workers, accept_callback_http);

    return 0;
}
<commit_msg>support svg content type<commit_after>#include <algorithm>
#include <experimental/string_view>
#include <unordered_map>
#include <vector>

#include <fcntl.h>
#include <netdb.h>
#include <netinet/tcp.h>

#include <sys/stat.h>
#include <unistd.h>

#include "core/yta_event_loop.h"
#include "http/yta_http.hpp"

#include "args.h"
#include "picohttpparser/picohttpparser.h"

const std::size_t MAX_URL_SIXE = 512;
const std::size_t MAX_HEADERS = 20;
const std::size_t MAX_BUFFER_SIZE = 1024;

typedef unsigned char byte;

struct parser_data {
    const char* method = nullptr;
    std::size_t method_len = 0;
    const char* path = nullptr;
    std::size_t path_len = 0;
    int pret = 0;
    int minor_version = 0;
    std::array<phr_header, MAX_HEADERS> headers;
    std::size_t num_headers = MAX_HEADERS;
};

struct user_data {
    std::size_t counter;

    std::array<char, MAX_BUFFER_SIZE> buf;
    std::array<char, MAX_BUFFER_SIZE> response_buf;

    bool finalized;

    std::size_t response_size;
    bool content;
    std::experimental::string_view extension;

    int file_fd;
    std::size_t file_size;
    std::size_t offset = 0;

    parser_data parser;

    struct stat file_stat;
};

void return_400(user_data* udata) {
    auto ret = yta::http::serve_400(udata->response_buf.data());
    udata->response_size = ret - udata->response_buf.data();
    udata->content = false;
    udata->finalized = true;
}

void return_404(user_data* udata) {
    auto ret = yta::http::serve_404(udata->response_buf.data());
    udata->response_size = ret - udata->response_buf.data();
    udata->content = false;
    udata->finalized = true;
}

std::unordered_map<std::experimental::string_view, std::experimental::string_view>
    mime_types{ { ".html", "text/html" },
                { ".css", "text/css" },
                { ".png", "image/png" },
                { ".jpg", "image/jpeg" },
                { ".jpeg", "image/jpeg" },
                { ".svg", "image/svg+xml" },
                { ".txt", "text/plain" },
                { ".js", "application/x-javascript" },
                { ".json", "application/json" },
                { ".pdf", "application/pdf" },
                { ".zip", "application/zip" },
                { ".woff", "application/font-woff" },
                { ".woff2", "application/font-woff2" },
                { ".opus", "audio/opus" },
                { ".mp4", "video/mp4" },
                { ".mpeg", "video/mpeg" },
                { ".mpg", "video/mpeg" },
                { ".mp3", "audio/mpeg" } };

int parse_url(yta_ctx* ctx, const char* path, size_t length) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    // parse query string
    auto pos = std::find(path, path + length, '?');
    if (pos != path + length) {
        length = pos - path;
    }

    // clean path buffer is MAX_URL_SICE
    // leave space for appended index.html
    if ((length > (MAX_URL_SIXE - 20)) || (length == 0)) {
        return_404(udata);
        return 0;
    }

    char normalized_path[MAX_URL_SIXE] = { 0 };
    // prepend . for current directory
    normalized_path[0] = '.';
    std::size_t new_length = 1;

    // clean path
    new_length += yta::http::clean_path(path, length, normalized_path + 1);

    // clean_path removes trailing slash except for root;
    // put the trailing slash back if necessary.
    if (path[length - 1] == '/' && new_length != 2) {
        normalized_path[new_length] = '/';
        ++new_length;
    }

    // append index.html to urls with trailing slashes
    if (normalized_path[new_length - 1] == '/') {
        const char index_html[] = "index.html";
        std::copy(std::begin(index_html), std::end(index_html),
                  normalized_path + new_length);
        new_length += 10;
    }

    int ffd = open(normalized_path, O_RDONLY);

    if (ffd == -1) {
        return_404(udata);
        return 0;
    }

    struct stat file_stat;
    int status = fstat(ffd, &file_stat);

    if (status != 0 || !S_ISREG(file_stat.st_mode)) {
        return_404(udata);
        close(ffd);
        return 0;
    }

    std::experimental::string_view path_view(normalized_path, new_length);
    auto filetype_begin = path_view.rfind('.');
    auto file_begin = path_view.rfind('/');

    // we always find . at the beginning because of ./FILENAME
    if (file_begin < filetype_begin) {
        auto it = mime_types.find(path_view.substr(filetype_begin));
        if (it != mime_types.end()) {
            udata->extension = it->second;
        } else {
            udata->extension = { "text/plain" };
        }
    } else {
        udata->extension = { "text/plain" };
    }

    udata->file_fd = ffd;
    udata->file_size = file_stat.st_size;
    udata->file_stat = file_stat;

    return 0;
}

typedef bool (*header_handler)(yta_ctx*, std::experimental::string_view);

bool handle_if_modified_since(yta_ctx* ctx, std::experimental::string_view value) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    tm stamp;
    if (strptime(value.data(), yta::http::http_time_format(), &stamp) == NULL) {
        auto end = yta::http::serve_400(udata->response_buf.data());
        udata->response_size = end - udata->response_buf.data();
        udata->content = false;
        udata->finalized = true;
        return true;
    }
    time_t time = timegm(&stamp);

    // not modified
    if (time >= udata->file_stat.st_mtime) {
        auto end = yta::http::serve_304(udata->response_buf.data());
        udata->response_size = end - udata->response_buf.data();
        udata->content = false;
        udata->finalized = true;
        return true;
    }

    return false;
}

bool handle_range(yta_ctx* ctx, std::experimental::string_view value) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    // 7 bytes=X-
    if (value.size() < 8) {
        return_400(udata);
        return true;
    }

    auto iter = value.begin();

    if (!std::equal(iter, iter + 6, "bytes=")) {
        return_400(udata);
        return true;
    }

    std::advance(iter, 6);

    auto sep = std::find(iter, value.end(), '-');

    if (sep == value.end()) {
        return_400(udata);
        return true;
    }

    // Range: bytes=-123
    if (sep == iter) {
        // this should be supported by rfc
        return_400(udata);
        return true;
    }

    // TODO: think of something smarter to not create temp std::string
    // boost::lexical_cast would work
    auto val = std::string(iter, sep);
    int start_value = std::stoi(val);
    int end_value = 0;

    if (std::next(sep, 1) == value.end()) { // Range: bytes=123-
        end_value = udata->file_stat.st_size - 1;
    } else { // Range: bytes=123-200
        auto val = std::string(sep + 1, value.end());
        end_value = std::stoi(val);
    }

    // sanity checks
    if (end_value <= start_value) {
        end_value = udata->file_stat.st_size - 1;
    }

    if (start_value < 0) {
        start_value = 0;
    }

    if (end_value >= udata->file_stat.st_size) {
        end_value = udata->file_stat.st_size - 1;
    }

    udata->file_size = end_value - start_value + 1;
    udata->offset = start_value;

    auto end = yta::http::serve_206(udata->response_buf.data(), udata->file_size,
                                    &udata->file_stat.st_mtime, start_value, end_value,
                                    udata->file_stat.st_size);
    udata->response_size = end - udata->response_buf.data();
    udata->content = true;
    udata->finalized = true;

    return true;
}

std::unordered_map<std::experimental::string_view, header_handler> header_callbacks{
    { "If-Modified-Since", handle_if_modified_since }, { "Range", handle_range }
};

int parse_headers(yta_ctx* ctx) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    for (std::size_t i = 0; (i < udata->parser.num_headers) && !udata->finalized; ++i) {
        std::experimental::string_view header(udata->parser.headers[i].name,
                                              udata->parser.headers[i].name_len);
        auto it = header_callbacks.find(header);
        if (it != header_callbacks.end()) {
            std::experimental::string_view value(udata->parser.headers[i].value,
                                                 udata->parser.headers[i].value_len);
            auto done = it->second(ctx, value);
            if (done) {
                return 0;
            }
        }
    }

    if (!udata->finalized) {
        auto end = yta::http::serve_200(udata->response_buf.data(), udata->file_size,
                                        &udata->file_stat.st_mtime, udata->extension);
        udata->response_size = end - udata->response_buf.data();
        udata->content = true;
        udata->finalized = true;
    }
    return 0;
}

void accept_logic(yta_ctx* ctx, user_data* udata);

yta_callback_status http_finish_callback(yta_ctx* ctx, void*, size_t) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    if (udata->file_fd != 0) {
        close(udata->file_fd);
        udata->file_fd = 0;
    }

    // uncork
    int enable = 0;
    if (setsockopt(ctx->fd, IPPROTO_TCP, TCP_CORK, &enable, sizeof(enable)) < 0) {
        fprintf(stderr, "error setting TCP_CORK");
        exit(1);
    }

    accept_logic(ctx, udata);
    return YTA_OK;
}

yta_callback_status write_header_callback(yta_ctx* ctx, void*, size_t) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);
    if (udata->content) {
        yta_async_sendfile(ctx, http_finish_callback, udata->file_fd, udata->file_size,
                           udata->offset);
        return YTA_OK;
    } else {
        return http_finish_callback(ctx, NULL, 0);
    }
}

yta_callback_status read_callback_http(yta_ctx* ctx, void* buf, size_t read) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    std::size_t prev_count = udata->counter;
    udata->counter += read;

    int parsed = phr_parse_request(
        udata->buf.data(), udata->counter, &udata->parser.method,
        &udata->parser.method_len, &udata->parser.path, &udata->parser.path_len,
        &udata->parser.minor_version, udata->parser.headers.data(),
        &udata->parser.num_headers, prev_count);

    if (parsed == -1) {
        return_400(udata);
    } else if (parsed > 0) {
        parse_url(ctx, udata->parser.path, udata->parser.path_len);
        parse_headers(ctx);
    }

    if (udata->finalized) {
        // cork
        int enable = 1;
        if (setsockopt(ctx->fd, IPPROTO_TCP, TCP_CORK, &enable, sizeof(enable)) < 0) {
            fprintf(stderr, "error setting TCP_CORK");
            exit(1);
        }

        yta_async_write(ctx, write_header_callback, udata->response_buf.data(),
                        udata->response_size);
        return YTA_OK;
    }

    if (udata->counter == MAX_BUFFER_SIZE) {
        return http_finish_callback(ctx, NULL, 0);
    }

    yta_async_read(ctx, read_callback_http, (char*)buf + read,
                   MAX_BUFFER_SIZE - udata->counter);
    return YTA_OK;
}

yta_callback_status http_cleanup(yta_ctx* ctx) {
    user_data* udata = static_cast<user_data*>(ctx->user_data);

    if (udata->file_fd != 0) {
        close(udata->file_fd);
        udata->file_fd = 0;
    }

    delete udata;

    return YTA_EXIT;
}

yta_callback_status timer_callback(yta_ctx* /* ctx */) {
    printf("Force closing http connection\n");
    return YTA_EXIT;
}

void accept_logic(yta_ctx* ctx, user_data* udata) {
    udata->parser = parser_data{};
    udata->counter = 0;
    udata->finalized = false;
    udata->file_fd = 0;
    yta_async_read(ctx, read_callback_http, udata->buf.data(), MAX_BUFFER_SIZE);
}

yta_callback_status accept_callback_http(yta_ctx* ctx) {
    user_data* udata = new user_data;
    if (udata == nullptr) {
        return YTA_EXIT;
    }
    ctx->user_data = udata;
    yta_set_close_callback(ctx, http_cleanup);
    yta_async_timer(ctx, timer_callback, 300, 0);
    accept_logic(ctx, udata);
    return YTA_OK;
}

int main(int argc, char** argv) {
    auto opts = get_program_opts(argc, argv);

    yta_run(argv, opts.host.c_str(), opts.port.c_str(), opts.pid_file.c_str(),
            opts.daemonize, opts.workers, accept_callback_http);

    return 0;
}
<|endoftext|>


<commit_before>#include "Game.hpp"
/******************************************************************************
** 								CONSTRUCTOR
******************************************************************************/

Game::Game (int enemyNbr) :  _enemyNbr(0), _enemyNbrMax(enemyNbr)
{
	std::srand(std::time(NULL) + std::clock());
	initscr();
	nodelay(stdscr, TRUE);
	keypad(stdscr, TRUE);
	curs_set(0);
	this->_box = stdscr;
	this->_map = new AEntity(getmaxx(stdscr) - 1, getmaxy(stdscr) - 1, 0, 1);
	this->_hero = new Hero(*new AEntity(3, 3, 1, 5));
	this->_initEnemy();

	this->_putEntity(this->_hero->getShape(), (this->_map->getSizeX() - this->_hero->getShape().getSizeX()) / 2,
	this->_map->getSizeY() - this->_hero->getShape().getSizeY());

	std::cout << "Init Game Constructor" << std::endl;

	return ;
}

Game::Game( Game const & src )
{
	std::cout << "Copy Game Constructor" << std::endl;
	*this = src;
	return ;
}
/******************************************************************************
** 							DESTRUCTOR
******************************************************************************/
Game::~Game( void )
{
	return ;
}
/******************************************************************************
** 							OPERATOR OVERLOAD
******************************************************************************/
Game & Game::operator=( Game const & rhs )
{
	this->_box = rhs._box;
	this->_map = rhs._map;
	this->_hero = rhs._hero;
	this->_enemies = rhs._enemies;
	this->_enemyNbr = rhs._enemyNbr;
	this->_enemyNbrMax = rhs._enemyNbrMax;

	return *this;
}

/******************************************************************************
** 							PRIVATE MEMBER FUNCTION
******************************************************************************/
void 		Game::_initEnemy(void)
{
	this->_enemies = new Enemy*[this->_enemyNbrMax];
	for (int i = 0; i < this->_enemyNbrMax; i++) {
		this->_enemies[i] = NULL;
	}

	return ;
}

void 		Game::_newWave(void)
{
	this->_enemyNbr = rand() % this->_enemyNbrMax;
	Enemy* (Game::*Func[])(void) const = {&Game::_callD7, &Game::_callVor_cha};

	for (int i = 0; i < this->_enemyNbr; i++) {
		if (!this->_enemies[i]) {
			this->_enemies[i] = (this->*Func[rand() % 2])();
			this->_putEntity(this->_enemies[i]->getShape(), ((this->_map->getSizeX() / (this->_enemyNbr)) * (i)) + 1, 5);
		}
	}

	return ;
}

void 		Game::_putEntity(AEntity &entity, int x, int y)
{
	int i = 0;
	int j = 0;

	entity.setPosX(x);
	entity.setPosY(y);

	for (i = 0; i < entity.getSizeX(); i++) {
		for (j = 0; j < entity.getSizeY(); j++) {

			if (entity.getDefinition()[i][j] != this->_map->getDefinition()[i + x][j + y] && this->_map->getDefinition()[i + x][j + y] != 0) {
				endwin();
				return exit(0);
			}

			if (entity.getDefinition()[i][j] != 0) {
				this->_map->setDefinition(i + x, j + y, entity.getDefinition()[i][j]);
			}

		}
	}
}

void 		Game::_deleteEntity(AEntity &entity)
{
	int i = 0;
	int j = 0;
	int x = entity.getPosX();
	int y = entity.getPosY();

	for (i = 0; i < entity.getSizeX(); i++) {
		for (j = 0; j < entity.getSizeY(); j++) {
			if (entity.getDefinition()[i][j] != 0) {
				this->_map->setDefinition(i + x, j + y, 0);
			}
		}
	}
}

bool 		Game::_moveEntityUp(AEntity &entity)
{
	if (entity.getPosY() > 1) {
		entity.setPosY(entity.getPosY() - 1);

		return true;
	}
	else {
		return false;
	}
}

bool 		Game::_moveEntityDown(AEntity &entity)
{
	if (entity.getPosY() + entity.getSizeY() < this->_map->getSizeY()) {
		entity.setPosY(entity.getPosY() + 1);

		return true;
	}
	else {
		return false;
	}
}

bool 		Game::_moveEntityLeft(AEntity &entity)
{
	if (entity.getPosX() > 1) {
		entity.setPosX(entity.getPosX() - 1);

		return true;
	}
	else {
		return false;
	}
}

bool 		Game::_moveEntityRight(AEntity &entity)
{
	if (entity.getPosX() + entity.getSizeX() < this->_map->getSizeX()) {
		entity.setPosX(entity.getPosX() + 1);

		return true;
	}
	else {
		return false;
	}
}

Enemy*			Game::_callD7(void) const
{
	return new D7(new IWeapon(), 0x0);
}

Enemy*	Game::_callVor_cha(void) const
{
	return new Vor_cha(new IWeapon(), 0x0);
}

/******************************************************************************
** 								GETTEUR
******************************************************************************/
WINDOW*		Game::getBox(void)
{
	return this->_box;
}

/******************************************************************************
** 								SETTEUR
******************************************************************************/
void 		Game::setBox(WINDOW* box)
{
	this->_box = box;

	return ;
}

/******************************************************************************
** 							PUBLIC MEMBER FUNCTION
******************************************************************************/
void Game::printMap(void)
{
	int i = 0;
	int j = 0;

	for (i = 0; i < this->_map->getSizeX(); i++) {
		for (j = 0; j < this->_map->getSizeY(); j++) {
			if (this->_map->getDefinition()[i][j] == 1) {
				mvwaddch(this->getBox(), j, i, '#');
			}
			else if (this->_map->getDefinition()[i][j] == 2) {
				mvwaddch(this->getBox(), j, i, '@');
			}
			else if (this->_map->getDefinition()[i][j] == 3) {
				mvwaddch(this->getBox(), j, i, '*');
			}
			else {
				mvwaddch(this->getBox(), j, i, ' ');
			}
		}
	}
}

void Game::eraseMap(void)
{
	int i = 0;
	int j = 0;

	for (i = 0; i < this->_map->getSizeX(); i++) {
		for (j = 0; j < this->_map->getSizeY(); j++) {
			if (this->_map->getDefinition()[i][j] != 0) {
				mvwaddch(this->getBox(), j, i, ' ');
			}
		}
	}
}

void 		Game::moveEntity(AEntity &entity, int vecteur)
{
	this->_deleteEntity(entity);

	switch (vecteur)
	{
	case 1: // haut
		this->_moveEntityUp(entity);
		break;

	case 2: // bas
		this->_moveEntityDown(entity);
		break;

	case 3: // gauche
		this->_moveEntityLeft(entity);
		break;

	case 4: // droite
		this->_moveEntityRight(entity);
		break;
	default:
		break;
	}

	this->_putEntity(entity, entity.getPosX(), entity.getPosY());

	return ;

}

void 		Game::moveEnemies(void)
{
	int i = 0;

	for (i = 0; i < this->_enemyNbrMax; i++) {
		if (this->_enemies[i] != NULL && this->_enemies[i]->move())
		{
			this->_deleteEntity(this->_enemies[i]->getShape());
			if (this->_enemies[i]->enemyMove(this->_map->getSizeX(), this->_map->getSizeY())) {
				this->_putEntity(this->_enemies[i]->getShape(), this->_enemies[i]->getShape().getPosX(), this->_enemies[i]->getShape().getPosY());
			}else{
				this->_enemyNbr--;
				delete this->_enemies[i];
				this->_enemies[i] = NULL;
			}
		}
	}

	return ;
}

void Game::play(int ch)
{
	if (ch == 27) {
		endwin();
		return exit(0);
	}
	if (ch == 259) {
		this->moveEntity(this->_hero->getShape(), 1);
	}
	if (ch == 258) {
		this->moveEntity(this->_hero->getShape(), 2);
	}
	if (ch == 260) {
		this->moveEntity(this->_hero->getShape(), 3);
	}
	if (ch == 261) {
		this->moveEntity(this->_hero->getShape(), 4);
	}

	if (this->_enemyNbr == 0) {
		this->_newWave();
	}
	else {
		this->moveEnemies();
	}

}
<commit_msg>set enemy at 0<commit_after>#include "Game.hpp"
/******************************************************************************
** 								CONSTRUCTOR
******************************************************************************/

Game::Game (int enemyNbr) :  _enemyNbr(0), _enemyNbrMax(enemyNbr)
{
	std::srand(std::time(NULL) + std::clock());
	initscr();
	nodelay(stdscr, TRUE);
	keypad(stdscr, TRUE);
	curs_set(0);
	this->_box = stdscr;
	this->_map = new AEntity(getmaxx(stdscr) - 1, getmaxy(stdscr) - 1, 0, 1);
	this->_hero = new Hero(*new AEntity(3, 3, 1, 5));
	this->_initEnemy();

	this->_putEntity(this->_hero->getShape(), (this->_map->getSizeX() - this->_hero->getShape().getSizeX()) / 2,
	this->_map->getSizeY() - this->_hero->getShape().getSizeY());

	std::cout << "Init Game Constructor" << std::endl;

	return ;
}

Game::Game( Game const & src )
{
	std::cout << "Copy Game Constructor" << std::endl;
	*this = src;
	return ;
}
/******************************************************************************
** 							DESTRUCTOR
******************************************************************************/
Game::~Game( void )
{
	return ;
}
/******************************************************************************
** 							OPERATOR OVERLOAD
******************************************************************************/
Game & Game::operator=( Game const & rhs )
{
	this->_box = rhs._box;
	this->_map = rhs._map;
	this->_hero = rhs._hero;
	this->_enemies = rhs._enemies;
	this->_enemyNbr = rhs._enemyNbr;
	this->_enemyNbrMax = rhs._enemyNbrMax;

	return *this;
}

/******************************************************************************
** 							PRIVATE MEMBER FUNCTION
******************************************************************************/
void 		Game::_initEnemy(void)
{
	this->_enemies = new Enemy*[this->_enemyNbrMax];
	for (int i = 0; i < this->_enemyNbrMax; i++) {
		this->_enemies[i] = NULL;
	}

	return ;
}

void 		Game::_newWave(void)
{
	this->_enemyNbr = rand() % this->_enemyNbrMax;
	Enemy* (Game::*Func[])(void) const = {&Game::_callD7, &Game::_callVor_cha};

	for (int i = 0; i < this->_enemyNbr; i++) {
		if (!this->_enemies[i]) {
			this->_enemies[i] = (this->*Func[rand() % 2])();
			this->_putEntity(this->_enemies[i]->getShape(), ((this->_map->getSizeX() / (this->_enemyNbr)) * (i)) + 1, 0);
		}
	}

	return ;
}

void 		Game::_putEntity(AEntity &entity, int x, int y)
{
	int i = 0;
	int j = 0;

	entity.setPosX(x);
	entity.setPosY(y);

	for (i = 0; i < entity.getSizeX(); i++) {
		for (j = 0; j < entity.getSizeY(); j++) {

			if (entity.getDefinition()[i][j] != this->_map->getDefinition()[i + x][j + y] && this->_map->getDefinition()[i + x][j + y] != 0) {
				endwin();
				return exit(0);
			}

			if (entity.getDefinition()[i][j] != 0) {
				this->_map->setDefinition(i + x, j + y, entity.getDefinition()[i][j]);
			}

		}
	}
}

void 		Game::_deleteEntity(AEntity &entity)
{
	int i = 0;
	int j = 0;
	int x = entity.getPosX();
	int y = entity.getPosY();

	for (i = 0; i < entity.getSizeX(); i++) {
		for (j = 0; j < entity.getSizeY(); j++) {
			if (entity.getDefinition()[i][j] != 0) {
				this->_map->setDefinition(i + x, j + y, 0);
			}
		}
	}
}

bool 		Game::_moveEntityUp(AEntity &entity)
{
	if (entity.getPosY() > 1) {
		entity.setPosY(entity.getPosY() - 1);

		return true;
	}
	else {
		return false;
	}
}

bool 		Game::_moveEntityDown(AEntity &entity)
{
	if (entity.getPosY() + entity.getSizeY() < this->_map->getSizeY()) {
		entity.setPosY(entity.getPosY() + 1);

		return true;
	}
	else {
		return false;
	}
}

bool 		Game::_moveEntityLeft(AEntity &entity)
{
	if (entity.getPosX() > 1) {
		entity.setPosX(entity.getPosX() - 1);

		return true;
	}
	else {
		return false;
	}
}

bool 		Game::_moveEntityRight(AEntity &entity)
{
	if (entity.getPosX() + entity.getSizeX() < this->_map->getSizeX()) {
		entity.setPosX(entity.getPosX() + 1);

		return true;
	}
	else {
		return false;
	}
}

Enemy*			Game::_callD7(void) const
{
	return new D7(new IWeapon(), 0x0);
}

Enemy*	Game::_callVor_cha(void) const
{
	return new Vor_cha(new IWeapon(), 0x0);
}

/******************************************************************************
** 								GETTEUR
******************************************************************************/
WINDOW*		Game::getBox(void)
{
	return this->_box;
}

/******************************************************************************
** 								SETTEUR
******************************************************************************/
void 		Game::setBox(WINDOW* box)
{
	this->_box = box;

	return ;
}

/******************************************************************************
** 							PUBLIC MEMBER FUNCTION
******************************************************************************/
void Game::printMap(void)
{
	int i = 0;
	int j = 0;

	for (i = 0; i < this->_map->getSizeX(); i++) {
		for (j = 0; j < this->_map->getSizeY(); j++) {
			if (this->_map->getDefinition()[i][j] == 1) {
				mvwaddch(this->getBox(), j, i, '#');
			}
			else if (this->_map->getDefinition()[i][j] == 2) {
				mvwaddch(this->getBox(), j, i, '@');
			}
			else if (this->_map->getDefinition()[i][j] == 3) {
				mvwaddch(this->getBox(), j, i, '*');
			}
			else {
				mvwaddch(this->getBox(), j, i, ' ');
			}
		}
	}
}

void Game::eraseMap(void)
{
	int i = 0;
	int j = 0;

	for (i = 0; i < this->_map->getSizeX(); i++) {
		for (j = 0; j < this->_map->getSizeY(); j++) {
			if (this->_map->getDefinition()[i][j] != 0) {
				mvwaddch(this->getBox(), j, i, ' ');
			}
		}
	}
}

void 		Game::moveEntity(AEntity &entity, int vecteur)
{
	this->_deleteEntity(entity);

	switch (vecteur)
	{
	case 1: // haut
		this->_moveEntityUp(entity);
		break;

	case 2: // bas
		this->_moveEntityDown(entity);
		break;

	case 3: // gauche
		this->_moveEntityLeft(entity);
		break;

	case 4: // droite
		this->_moveEntityRight(entity);
		break;
	default:
		break;
	}

	this->_putEntity(entity, entity.getPosX(), entity.getPosY());

	return ;

}

void 		Game::moveEnemies(void)
{
	int i = 0;

	for (i = 0; i < this->_enemyNbrMax; i++) {
		if (this->_enemies[i] != NULL && this->_enemies[i]->move())
		{
			this->_deleteEntity(this->_enemies[i]->getShape());
			if (this->_enemies[i]->enemyMove(this->_map->getSizeX(), this->_map->getSizeY())) {
				this->_putEntity(this->_enemies[i]->getShape(), this->_enemies[i]->getShape().getPosX(), this->_enemies[i]->getShape().getPosY());
			}else{
				this->_enemyNbr--;
				delete this->_enemies[i];
				this->_enemies[i] = NULL;
			}
		}
	}

	return ;
}

void Game::play(int ch)
{
	if (ch == 27) {
		endwin();
		return exit(0);
	}
	if (ch == 259) {
		this->moveEntity(this->_hero->getShape(), 1);
	}
	if (ch == 258) {
		this->moveEntity(this->_hero->getShape(), 2);
	}
	if (ch == 260) {
		this->moveEntity(this->_hero->getShape(), 3);
	}
	if (ch == 261) {
		this->moveEntity(this->_hero->getShape(), 4);
	}

	if (this->_enemyNbr == 0) {
		this->_newWave();
	}
	else {
		this->moveEnemies();
	}

}
<|endoftext|>


<commit_before>/*
   Copyright (C) 2013, 2014 Andreas Hartmetz <ahartmetz@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LGPL.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.

   Alternatively, this file is available under the Mozilla Public License
   Version 1.1.  You may obtain a copy of the License at
   http://www.mozilla.org/MPL/
*/

#include "peeraddress.h"

#include "stringtools.h"

#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <vector>

#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>

using namespace std;

static string homeDir()
{
    const char *home = getenv("HOME"); // this overrides the entry in /etc/passwd
    if (!home) {
        // from /etc/passwd (or a similar mechanism)
        // ### user's storage is static; consider using getpwuid_r though!
        struct passwd *user = getpwuid(getuid());
        if (user) {
            home = user->pw_dir;
        }
    }
    assert(home);
    return string(home);
}

static string sessionInfoFile()
{
    static const int numMachineUuidFilenames = 2;
    static const char *machineUuidFilenames[numMachineUuidFilenames] = {
        "/var/lib/dbus/machine-id",
        "/etc/machine-id"
    };

    string uuid;
    for (int i = 0; i < numMachineUuidFilenames && uuid.empty(); i++) {
        ifstream uuidFile(machineUuidFilenames[i]);
        uuidFile >> uuid;
        // TODO check that uuid consists of lowercase hex chars
    }
    if (uuid.length() != 32) {
        return string();
    }

    const char *displayChar = getenv("DISPLAY");
    if (!displayChar) {
        // TODO error message "no X11 session blah"
        return string();
    }
    string display = displayChar;
    // TODO from the original: "Note that we leave the hostname in the display most of the time"
    size_t lastColon = display.rfind(':');
    if (lastColon == string::npos) {
        return string();
    }
    display.erase(0, lastColon + 1);

    static const char *pathInHome = "/.dbus/session-bus/";
    string ret = homeDir() + pathInHome + uuid + '-' + display;
    return ret;
}

class PeerAddress::Private
{
public:
    Private()
       : m_peerType(NoPeer),
         m_socketType(NoSocket),
         m_port(-1)
    {}

    void fetchSessionBusInfo();
    void parseSessionBusInfo(std::string info);

    PeerAddress::PeerType m_peerType;
    PeerAddress::SocketType m_socketType;
    std::string m_path;
    int m_port;
    std::string m_guid;
};

PeerAddress::PeerAddress()
   : d(new Private)
{
}

PeerAddress::PeerAddress(PeerType bus)
   : d(new Private)
{
    if (bus == SessionBus) {
        d->fetchSessionBusInfo();
    } else if (bus == SystemBus) {
        // TODO non-Linux
        d->m_path = "/var/run/dbus/system_bus_socket";
    } else {
        // TODO error
    }
}

PeerAddress::PeerAddress(const PeerAddress &other)
   : d(new Private(*other.d))
{
}

PeerAddress &PeerAddress::operator=(const PeerAddress &other)
{
    *d = *other.d;
    return *this;
}

PeerAddress::~PeerAddress()
{
    delete d;
    d = 0;
}

PeerAddress::PeerType PeerAddress::peerType() const
{
    return d->m_peerType;
}

PeerAddress::SocketType PeerAddress::socketType() const
{
    return d->m_socketType;
}

string PeerAddress::path() const
{
    return d->m_path;
}

int PeerAddress::port() const
{
    return d->m_port;
}

string PeerAddress::guid() const
{
    return d->m_guid;
}

void PeerAddress::Private::fetchSessionBusInfo()
{
    ifstream infoFile(sessionInfoFile().c_str());
    string line;

    // TODO: on X, the spec requires a special way to find the session bus

    // try the environment variable
    const char *envAddress = getenv("DBUS_SESSION_BUS_ADDRESS");
    if (envAddress) {
        line = envAddress;
    } else {
        // try it using a byzantine system involving files...
        string busAddressPrefix = "DBUS_SESSION_BUS_ADDRESS=";
        while (getline(infoFile, line)) {
            // TODO do we need any of the other information in the file?
            if (line.find(busAddressPrefix) == 0 ) {
                line = line.substr(busAddressPrefix.length());
                break;
            }
        }
    }

    parseSessionBusInfo(line);
}

void PeerAddress::Private::parseSessionBusInfo(string info)
{
    SocketType provisionalType = NoSocket;

    string unixAddressLiteral = "unix:";
    string guidLiteral = "guid=";

    if (info.find(unixAddressLiteral) == 0) {
        provisionalType = UnixSocket;
        info.erase(0, unixAddressLiteral.length());
    }

    // TODO is there any escaping?
    const vector<string> parts = split(info, ',');

    if (provisionalType == UnixSocket) {
        string pathLiteral = "path=";
        string abstractLiteral = "abstract=";
        // TODO what about "tmpdir=..."?

        for (int i = 0; i < parts.size(); i++) {
            const string &part = parts[i];
            if (part.find(pathLiteral) == 0) {
                if (m_socketType != NoSocket) {
                    goto invalid; // error - duplicate path specification
                }
                m_socketType = UnixSocket;
                m_path = part.substr(pathLiteral.length());
            } else if (part.find(abstractLiteral) == 0) {
                if (m_socketType != NoSocket) {
                    goto invalid;
                }
                m_socketType = AbstractUnixSocket;
                m_path = part.substr(abstractLiteral.length());
            }
        }
    } else {
        // TODO
    }

    for (int i = 0; i < parts.size(); i++) {
        const string &part = parts[i];
        if (part.find(guidLiteral) == 0) {
            m_guid = part.substr(guidLiteral.length());
        }
    }

    return;
invalid:
    m_socketType = NoSocket;
    m_path.clear();
}
<commit_msg>PeerAddress: initialize more variables in PeerType constructor.<commit_after>/*
   Copyright (C) 2013, 2014 Andreas Hartmetz <ahartmetz@gmail.com>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library 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
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LGPL.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.

   Alternatively, this file is available under the Mozilla Public License
   Version 1.1.  You may obtain a copy of the License at
   http://www.mozilla.org/MPL/
*/

#include "peeraddress.h"

#include "stringtools.h"

#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <vector>

#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>

using namespace std;

static string homeDir()
{
    const char *home = getenv("HOME"); // this overrides the entry in /etc/passwd
    if (!home) {
        // from /etc/passwd (or a similar mechanism)
        // ### user's storage is static; consider using getpwuid_r though!
        struct passwd *user = getpwuid(getuid());
        if (user) {
            home = user->pw_dir;
        }
    }
    assert(home);
    return string(home);
}

static string sessionInfoFile()
{
    static const int numMachineUuidFilenames = 2;
    static const char *machineUuidFilenames[numMachineUuidFilenames] = {
        "/var/lib/dbus/machine-id",
        "/etc/machine-id"
    };

    string uuid;
    for (int i = 0; i < numMachineUuidFilenames && uuid.empty(); i++) {
        ifstream uuidFile(machineUuidFilenames[i]);
        uuidFile >> uuid;
        // TODO check that uuid consists of lowercase hex chars
    }
    if (uuid.length() != 32) {
        return string();
    }

    const char *displayChar = getenv("DISPLAY");
    if (!displayChar) {
        // TODO error message "no X11 session blah"
        return string();
    }
    string display = displayChar;
    // TODO from the original: "Note that we leave the hostname in the display most of the time"
    size_t lastColon = display.rfind(':');
    if (lastColon == string::npos) {
        return string();
    }
    display.erase(0, lastColon + 1);

    static const char *pathInHome = "/.dbus/session-bus/";
    string ret = homeDir() + pathInHome + uuid + '-' + display;
    return ret;
}

class PeerAddress::Private
{
public:
    Private()
       : m_peerType(NoPeer),
         m_socketType(NoSocket),
         m_port(-1)
    {}

    void fetchSessionBusInfo();
    void parseSessionBusInfo(std::string info);

    PeerAddress::PeerType m_peerType;
    PeerAddress::SocketType m_socketType;
    std::string m_path;
    int m_port;
    std::string m_guid;
};

PeerAddress::PeerAddress()
   : d(new Private)
{
}

PeerAddress::PeerAddress(PeerType bus)
   : d(new Private)
{
    d->m_peerType = bus;
    if (bus == SessionBus) {
        d->fetchSessionBusInfo();
    } else if (bus == SystemBus) {
        // TODO non-Linux
        d->m_socketType = UnixSocket;
        d->m_path = "/var/run/dbus/system_bus_socket";
    } else {
        // TODO error
    }
}

PeerAddress::PeerAddress(const PeerAddress &other)
   : d(new Private(*other.d))
{
}

PeerAddress &PeerAddress::operator=(const PeerAddress &other)
{
    *d = *other.d;
    return *this;
}

PeerAddress::~PeerAddress()
{
    delete d;
    d = 0;
}

PeerAddress::PeerType PeerAddress::peerType() const
{
    return d->m_peerType;
}

PeerAddress::SocketType PeerAddress::socketType() const
{
    return d->m_socketType;
}

string PeerAddress::path() const
{
    return d->m_path;
}

int PeerAddress::port() const
{
    return d->m_port;
}

string PeerAddress::guid() const
{
    return d->m_guid;
}

void PeerAddress::Private::fetchSessionBusInfo()
{
    ifstream infoFile(sessionInfoFile().c_str());
    string line;

    // TODO: on X, the spec requires a special way to find the session bus

    // try the environment variable
    const char *envAddress = getenv("DBUS_SESSION_BUS_ADDRESS");
    if (envAddress) {
        line = envAddress;
    } else {
        // try it using a byzantine system involving files...
        string busAddressPrefix = "DBUS_SESSION_BUS_ADDRESS=";
        while (getline(infoFile, line)) {
            // TODO do we need any of the other information in the file?
            if (line.find(busAddressPrefix) == 0 ) {
                line = line.substr(busAddressPrefix.length());
                break;
            }
        }
    }

    parseSessionBusInfo(line);
}

void PeerAddress::Private::parseSessionBusInfo(string info)
{
    SocketType provisionalType = NoSocket;

    string unixAddressLiteral = "unix:";
    string guidLiteral = "guid=";

    if (info.find(unixAddressLiteral) == 0) {
        provisionalType = UnixSocket;
        info.erase(0, unixAddressLiteral.length());
    }

    // TODO is there any escaping?
    const vector<string> parts = split(info, ',');

    if (provisionalType == UnixSocket) {
        string pathLiteral = "path=";
        string abstractLiteral = "abstract=";
        // TODO what about "tmpdir=..."?

        for (int i = 0; i < parts.size(); i++) {
            const string &part = parts[i];
            if (part.find(pathLiteral) == 0) {
                if (m_socketType != NoSocket) {
                    goto invalid; // error - duplicate path specification
                }
                m_socketType = UnixSocket;
                m_path = part.substr(pathLiteral.length());
            } else if (part.find(abstractLiteral) == 0) {
                if (m_socketType != NoSocket) {
                    goto invalid;
                }
                m_socketType = AbstractUnixSocket;
                m_path = part.substr(abstractLiteral.length());
            }
        }
    } else {
        // TODO
    }

    for (int i = 0; i < parts.size(); i++) {
        const string &part = parts[i];
        if (part.find(guidLiteral) == 0) {
            m_guid = part.substr(guidLiteral.length());
        }
    }

    return;
invalid:
    m_socketType = NoSocket;
    m_path.clear();
}
<|endoftext|>