static int rumpsp_dispatch(int timeout_ms) { unsigned int idx; int rv, seen; rv = poll(pollfds, maxidx+1, timeout_ms); if (rv == 0) return 0; if (rv < 0) return errno; seen = 0; for (idx = 0; seen < rv && idx <= maxidx; idx++) { struct rumpsp_chan *chan = &chanfds[idx]; if (!(pollfds[idx].revents & (POLLIN|POLLOUT))) continue; seen++; if (idx == 0) { dispatch_accept(chan->fd); } else { if (pollfds[idx].revents & POLLIN) { handlers.readable(chan, chan->token); } if (pollfds[idx].revents & POLLOUT) { handlers.writable(chan, chan->token); } } } return 0; }
int main(int argc, char * argv[]) { /* State variables. */ struct serverpool * SP; struct dynamodb_request_queue * QW; struct dynamodb_request_queue * QR; struct dispatch_state * D; int s; /* Command-line parameters. */ char * opt_k = NULL; char * opt_l = NULL; char * opt_p = NULL; char * opt_r = NULL; char * opt_s = NULL; char * opt_t = NULL; int opt_1 = 0; /* Working variable. */ char * dynamodb_host; char * key_id; char * key_secret; struct sock_addr ** sas; struct logging_file * logfile; struct capacity_reader * M; const char * ch; WARNP_INIT; /* Parse the command line. */ while ((ch = GETOPT(argc, argv)) != NULL) { GETOPT_SWITCH(ch) { GETOPT_OPTARG("-k"): if (opt_k != NULL) usage(); if ((opt_k = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPTARG("-l"): if (opt_l != NULL) usage(); if ((opt_l = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPTARG("-p"): if (opt_p != NULL) usage(); if ((opt_p = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPTARG("-r"): if (opt_r != NULL) usage(); if ((opt_r = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPTARG("-s"): if (opt_s != NULL) usage(); if ((opt_s = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPTARG("-t"): if (opt_t != NULL) usage(); if ((opt_t = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPT("--version"): fprintf(stderr, "dynamodb-kv @VERSION@\n"); exit(0); GETOPT_OPT("-1"): if (opt_1 != 0) usage(); opt_1 = 1; break; GETOPT_MISSING_ARG: warn0("Missing argument to %s\n", ch); usage(); GETOPT_DEFAULT: warn0("illegal option -- %s\n", ch); usage(); } } argc -= optind; argv += optind; /* We should have processed all the arguments. */ if (argc != 0) usage(); /* Verify that we have mandatory options. */ if (opt_k == NULL) usage(); if (opt_r == NULL) usage(); if (opt_s == NULL) usage(); if (opt_t == NULL) usage(); /* Construct the DynamoDB endpoint host name. */ if (asprintf(&dynamodb_host, "dynamodb.%s.amazonaws.com:80", opt_r) == -1) { warnp("asprintf"); exit(1); } /* Start looking up addresses for DynamoDB endpoints. */ if ((SP = serverpool_create(dynamodb_host, 15, 120)) == NULL) { warnp("Error starting DNS lookups for %s", dynamodb_host); exit(1); } /* Read the key file. */ if (aws_readkeys(opt_k, &key_id, &key_secret)) { warnp("Error reading AWS keys from %s", opt_k); exit(1); } /* Create DynamoDB request queues for writes and reads. */ if ((QW = dynamodb_request_queue_init(key_id, key_secret, opt_r, SP)) == NULL) { warnp("Error creating DynamoDB request queue"); exit(1); } if ((QR = dynamodb_request_queue_init(key_id, key_secret, opt_r, SP)) == NULL) { warnp("Error creating DynamoDB request queue"); exit(1); } /* Start reading table throughput parameters. */ if ((M = capacity_init(key_id, key_secret, opt_t, opt_r, SP, QW, QR)) == NULL) { warnp("Error reading DynamoDB table metadata"); exit(1); } /* Resolve the listening address. */ if ((sas = sock_resolve(opt_s)) == NULL) { warnp("Error resolving socket address: %s", opt_s); exit(1); } if (sas[0] == NULL) { warn0("No addresses found for %s", opt_s); exit(1); } /* Create and bind a socket, and mark it as listening. */ if (sas[1] != NULL) warn0("Listening on first of multiple addresses found for %s", opt_s); if ((s = sock_listener(sas[0])) == -1) exit(1); /* If requested, create a log file. */ if (opt_l != NULL) { if ((logfile = logging_open(opt_l)) == NULL) { warnp("Cannot open log file"); exit(1); } dynamodb_request_queue_log(QW, logfile); dynamodb_request_queue_log(QR, logfile); } else { logfile = NULL; } /* Daemonize and write pid. */ if (opt_p == NULL) { if (asprintf(&opt_p, "%s.pid", opt_s) == -1) { warnp("asprintf"); exit(1); } } if (daemonize(opt_p)) { warnp("Failed to daemonize"); exit(1); } /* Handle connections, one at once. */ do { /* accept a connection. */ if ((D = dispatch_accept(QW, QR, opt_t, s)) == NULL) { warnp("Error accepting new connection"); exit(1); } /* Loop until the connection dies. */ do { if (events_run()) { warnp("Error running event loop"); exit(1); } } while (dispatch_alive(D)); /* Clean up the connection. */ if (dispatch_done(D)) exit(1); } while (opt_1 == 0); /* Close the log file, if we have one. */ if (logfile != NULL) logging_close(logfile); /* Close the listening socket. */ close(s); /* Free the address structures. */ sock_addr_freelist(sas); /* Stop performing DescribeTable requests. */ capacity_free(M); /* Free DynamoDB request queues. */ dynamodb_request_queue_free(QR); dynamodb_request_queue_free(QW); /* Stop DNS lookups. */ serverpool_free(SP); /* Shut down the event subsystem. */ events_shutdown(); /* Free string allocated by asprintf. */ free(dynamodb_host); /* Free key strings. */ free(key_id); insecure_memzero(key_secret, strlen(key_secret)); free(key_secret); /* Free option strings. */ free(opt_k); free(opt_l); free(opt_p); free(opt_r); free(opt_s); free(opt_t); /* Success! */ exit(0); }
int main(int argc, char * argv[]) { /* Command-line parameters. */ int opt_d = 0; int opt_D = 0; int opt_e = 0; int opt_f = 0; int opt_F = 0; int opt_j = 0; const char * opt_k = NULL; intmax_t opt_n = 0; double opt_o = 0.0; char * opt_p = NULL; double opt_r = 0.0; int opt_R = 0; const char * opt_s = NULL; const char * opt_t = NULL; /* Working variables. */ struct sock_addr ** sas_s; struct sock_addr ** sas_t; struct proto_secret * K; int ch; int s; WARNP_INIT; /* Parse the command line. */ while ((ch = getopt(argc, argv, "dDefFjk:n:o:r:Rp:s:t:")) != -1) { switch (ch) { case 'd': if (opt_d || opt_e) usage(); opt_d = 1; break; case 'D': if (opt_D) usage(); opt_D = 1; break; case 'e': if (opt_d || opt_e) usage(); opt_e = 1; break; case 'f': if (opt_f) usage(); opt_f = 1; break; case 'F': if (opt_F) usage(); opt_F = 1; break; case 'j': if (opt_j) usage(); opt_j = 1; break; case 'k': if (opt_k) usage(); opt_k = optarg; break; case 'n': if (opt_n != 0) usage(); if ((opt_n = strtoimax(optarg, NULL, 0)) == 0) { warn0("Invalid option: -n %s", optarg); exit(1); } break; case 'o': if (opt_o != 0.0) usage(); if ((opt_o = strtod(optarg, NULL)) == 0.0) { warn0("Invalid option: -o %s", optarg); exit(1); } break; case 'p': if (opt_p) usage(); if ((opt_p = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; case 'r': if (opt_r != 0.0) usage(); if ((opt_r = strtod(optarg, NULL)) == 0.0) { warn0("Invalid option: -r %s", optarg); exit(1); } break; case 'R': if (opt_R) usage(); opt_R = 1; break; case 's': if (opt_s) usage(); opt_s = optarg; break; case 't': if (opt_t) usage(); opt_t = optarg; break; default: usage(); } } /* We should have processed all the arguments. */ if (argc != optind) usage(); /* Set defaults. */ if (opt_n == 0) opt_n = 100; if (opt_o == 0.0) opt_o = 5.0; if (opt_r == 0.0) opt_r = 60.0; /* Sanity-check options. */ if (!opt_d && !opt_e) usage(); if (opt_k == NULL) usage(); if ((opt_n < 0) || (opt_n > 500)) usage(); if (!(opt_o > 0.0)) usage(); if ((opt_r != 60.0) && opt_R) usage(); if (opt_s == NULL) usage(); if (opt_t == NULL) usage(); /* Figure out where our pid should be written. */ if (opt_p == NULL) { if (asprintf(&opt_p, "%s.pid", opt_s) == -1) { warnp("asprintf"); exit(1); } } /* Daemonize early if we're going to wait for DNS to be ready. */ if (opt_D && !opt_F && daemonize(opt_p)) { warnp("Failed to daemonize"); exit(1); } /* Resolve source address. */ while ((sas_s = sock_resolve(opt_s)) == NULL) { if (!opt_D) { warnp("Error resolving socket address: %s", opt_s); exit(1); } sleep(1); } if (sas_s[0] == NULL) { warn0("No addresses found for %s", opt_s); exit(1); } /* Resolve target address. */ while ((sas_t = sock_resolve(opt_t)) == NULL) { if (!opt_D) { warnp("Error resolving socket address: %s", opt_t); exit(1); } sleep(1); } if (sas_t[0] == NULL) { warn0("No addresses found for %s", opt_t); exit(1); } /* Load the keying data. */ if ((K = proto_crypt_secret(opt_k)) == NULL) { warnp("Error reading shared secret"); exit(1); } /* Create and bind a socket, and mark it as listening. */ if (sas_s[1] != NULL) warn0("Listening on first of multiple addresses found for %s", opt_s); if ((s = sock_listener(sas_s[0])) == -1) exit(1); /* Daemonize and write pid. */ if (!opt_F && daemonize(opt_p)) { warnp("Failed to daemonize"); exit(1); } /* Start accepting connections. */ if (dispatch_accept(s, opt_t, opt_R ? 0.0 : opt_r, sas_t, opt_d, opt_f, opt_j, K, opt_n, opt_o)) { warnp("Failed to initialize connection acceptor"); exit(1); } /* Infinite loop handling events. */ do { if (events_run()) { warnp("Error running event loop"); exit(1); } } while (1); /* NOTREACHED */ /* * If we could reach this point, we would free memory, close sockets, * and otherwise clean up here. */ }
int main(int argc, char * argv[]) { /* Command-line parameters. */ int opt_d = 0; int opt_D = 0; int opt_e = 0; int opt_f = 0; int opt_g = 0; int opt_F = 0; int opt_j = 0; const char * opt_k = NULL; intmax_t opt_n = 0; double opt_o = 0.0; char * opt_p = NULL; double opt_r = 0.0; int opt_R = 0; const char * opt_s = NULL; const char * opt_t = NULL; /* Working variables. */ struct sock_addr ** sas_s; struct sock_addr ** sas_t; struct proto_secret * K; const char * ch; int s; WARNP_INIT; /* Parse the command line. */ while ((ch = GETOPT(argc, argv)) != NULL) { GETOPT_SWITCH(ch) { GETOPT_OPT("-d"): if (opt_d || opt_e) usage(); opt_d = 1; break; GETOPT_OPT("-D"): if (opt_D) usage(); opt_D = 1; break; GETOPT_OPT("-e"): if (opt_d || opt_e) usage(); opt_e = 1; break; GETOPT_OPT("-f"): if (opt_f) usage(); opt_f = 1; break; GETOPT_OPT("-F"): if (opt_F) usage(); opt_F = 1; break; GETOPT_OPT("-g"): if (opt_g) usage(); opt_g = 1; break; GETOPT_OPT("-j"): if (opt_j) usage(); opt_j = 1; break; GETOPT_OPTARG("-k"): if (opt_k) usage(); opt_k = optarg; break; GETOPT_OPTARG("-n"): if (opt_n != 0) usage(); if ((opt_n = strtoimax(optarg, NULL, 0)) == 0) { warn0("Invalid option: -n %s", optarg); exit(1); } if ((opt_n <= 0) || (opt_n > 500)) { warn0("The parameter to -n must be between 1 and 500\n"); exit(1); } break; GETOPT_OPTARG("-o"): if (opt_o != 0.0) usage(); if ((opt_o = strtod(optarg, NULL)) == 0.0) { warn0("Invalid option: -o %s", optarg); exit(1); } break; GETOPT_OPTARG("-p"): if (opt_p) usage(); if ((opt_p = strdup(optarg)) == NULL) OPT_EPARSE(ch, optarg); break; GETOPT_OPTARG("-r"): if (opt_r != 0.0) usage(); if ((opt_r = strtod(optarg, NULL)) == 0.0) { warn0("Invalid option: -r %s", optarg); exit(1); } break; GETOPT_OPT("-R"): if (opt_R) usage(); opt_R = 1; break; GETOPT_OPTARG("-s"): if (opt_s) usage(); opt_s = optarg; break; GETOPT_OPTARG("-t"): if (opt_t) usage(); opt_t = optarg; break; GETOPT_OPT("-v"): fprintf(stderr, "spiped @VERSION@\n"); exit(0); GETOPT_MISSING_ARG: warn0("Missing argument to %s\n", ch); /* FALLTHROUGH */ GETOPT_DEFAULT: usage(); } } argc -= optind; argv += optind; /* We should have processed all the arguments. */ if (argc != 0) usage(); /* Set defaults. */ if (opt_n == 0) opt_n = 100; if (opt_o == 0.0) opt_o = 5.0; if (opt_r == 0.0) opt_r = 60.0; /* Sanity-check options. */ if (!opt_d && !opt_e) usage(); if (opt_f && opt_g) usage(); if (opt_k == NULL) usage(); if (!(opt_o > 0.0)) usage(); if ((opt_r != 60.0) && opt_R) usage(); if (opt_s == NULL) usage(); if (opt_t == NULL) usage(); /* Figure out where our pid should be written. */ if (opt_p == NULL) { if (asprintf(&opt_p, "%s.pid", opt_s) == -1) { warnp("asprintf"); exit(1); } } /* Check whether we are running as init (e.g., inside a container). */ if (getpid() == 1) { /* https://github.com/docker/docker/issues/7086 */ warn0("WARNING: Applying workaround for Docker signal-handling bug"); /* Bind an explicit signal handler for SIGTERM and SIGINT. */ if (signal(SIGTERM, diediedie_handler) == SIG_ERR) { warnp("Failed to bind SIGTERM signal handler"); } if (signal(SIGINT, diediedie_handler) == SIG_ERR) { warnp("Failed to bind SIGINT signal handler"); } } /* Daemonize early if we're going to wait for DNS to be ready. */ if (opt_D && !opt_F && daemonize(opt_p)) { warnp("Failed to daemonize"); exit(1); } /* Resolve source address. */ while ((sas_s = sock_resolve(opt_s)) == NULL) { if (!opt_D) { warnp("Error resolving socket address: %s", opt_s); exit(1); } sleep(1); } if (sas_s[0] == NULL) { warn0("No addresses found for %s", opt_s); exit(1); } /* Resolve target address. */ while ((sas_t = sock_resolve(opt_t)) == NULL) { if (!opt_D) { warnp("Error resolving socket address: %s", opt_t); exit(1); } sleep(1); } if (sas_t[0] == NULL) { warn0("No addresses found for %s", opt_t); exit(1); } /* Load the keying data. */ if ((K = proto_crypt_secret(opt_k)) == NULL) { warnp("Error reading shared secret"); exit(1); } /* Create and bind a socket, and mark it as listening. */ if (sas_s[1] != NULL) warn0("Listening on first of multiple addresses found for %s", opt_s); if ((s = sock_listener(sas_s[0])) == -1) exit(1); /* Daemonize and write pid. */ if (!opt_F && daemonize(opt_p)) { warnp("Failed to daemonize"); exit(1); } /* Start accepting connections. */ if (dispatch_accept(s, opt_t, opt_R ? 0.0 : opt_r, sas_t, opt_d, opt_f, opt_g, opt_j, K, opt_n, opt_o)) { warnp("Failed to initialize connection acceptor"); exit(1); } /* Infinite loop handling events. */ do { if (events_run()) { warnp("Error running event loop"); exit(1); } } while (1); /* NOTREACHED */ /* * If we could reach this point, we would free memory, close sockets, * and otherwise clean up here. */ }