|
|
|
@ -47,6 +47,7 @@ |
|
|
|
|
#include <grpc/grpc.h> |
|
|
|
|
#include <grpc/support/alloc.h> |
|
|
|
|
#include <grpc/support/log.h> |
|
|
|
|
#include <grpc/support/string_util.h> |
|
|
|
|
|
|
|
|
|
#include "src/core/httpcli/httpcli.h" |
|
|
|
|
#include "src/core/support/env.h" |
|
|
|
@ -66,7 +67,70 @@ static int has_port_been_chosen(int port) { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void free_chosen_ports() { gpr_free(chosen_ports); } |
|
|
|
|
typedef struct freereq { |
|
|
|
|
grpc_pollset pollset; |
|
|
|
|
int done; |
|
|
|
|
} freereq; |
|
|
|
|
|
|
|
|
|
static void destroy_pollset_and_shutdown(void *p) { |
|
|
|
|
grpc_pollset_destroy(p); |
|
|
|
|
grpc_shutdown(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void freed_port_from_server(void *arg, |
|
|
|
|
const grpc_httpcli_response *response) { |
|
|
|
|
freereq *pr = arg; |
|
|
|
|
gpr_mu_lock(GRPC_POLLSET_MU(&pr->pollset)); |
|
|
|
|
pr->done = 1; |
|
|
|
|
grpc_pollset_kick(&pr->pollset, NULL); |
|
|
|
|
gpr_mu_unlock(GRPC_POLLSET_MU(&pr->pollset)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void free_port_using_server(char *server, int port) { |
|
|
|
|
grpc_httpcli_context context; |
|
|
|
|
grpc_httpcli_request req; |
|
|
|
|
freereq pr; |
|
|
|
|
char *path; |
|
|
|
|
|
|
|
|
|
grpc_init(); |
|
|
|
|
|
|
|
|
|
memset(&pr, 0, sizeof(pr)); |
|
|
|
|
memset(&req, 0, sizeof(req)); |
|
|
|
|
grpc_pollset_init(&pr.pollset); |
|
|
|
|
|
|
|
|
|
req.host = server; |
|
|
|
|
gpr_asprintf(&path, "/drop/%d", port); |
|
|
|
|
req.path = path; |
|
|
|
|
|
|
|
|
|
grpc_httpcli_context_init(&context); |
|
|
|
|
grpc_httpcli_get(&context, &pr.pollset, &req, |
|
|
|
|
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10), freed_port_from_server, |
|
|
|
|
&pr); |
|
|
|
|
gpr_mu_lock(GRPC_POLLSET_MU(&pr.pollset)); |
|
|
|
|
while (!pr.done) { |
|
|
|
|
grpc_pollset_worker worker; |
|
|
|
|
grpc_pollset_work(&pr.pollset, &worker, gpr_now(GPR_CLOCK_MONOTONIC), |
|
|
|
|
GRPC_TIMEOUT_SECONDS_TO_DEADLINE(1)); |
|
|
|
|
} |
|
|
|
|
gpr_mu_unlock(GRPC_POLLSET_MU(&pr.pollset)); |
|
|
|
|
|
|
|
|
|
grpc_httpcli_context_destroy(&context); |
|
|
|
|
grpc_pollset_shutdown(&pr.pollset, destroy_pollset_and_shutdown, &pr.pollset); |
|
|
|
|
gpr_free(path); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void free_chosen_ports() {
|
|
|
|
|
char *env = gpr_getenv("GRPC_TEST_PORT_SERVER"); |
|
|
|
|
if (env != NULL) { |
|
|
|
|
size_t i; |
|
|
|
|
for (i = 0; i < num_chosen_ports; i++) { |
|
|
|
|
free_port_using_server(env, chosen_ports[i]); |
|
|
|
|
} |
|
|
|
|
gpr_free(env); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gpr_free(chosen_ports);
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void chose_port(int port) { |
|
|
|
|
if (chosen_ports == NULL) { |
|
|
|
@ -131,6 +195,9 @@ static int is_port_available(int *port, int is_tcp) { |
|
|
|
|
typedef struct portreq { |
|
|
|
|
grpc_pollset pollset; |
|
|
|
|
int port; |
|
|
|
|
int retries; |
|
|
|
|
char *server; |
|
|
|
|
grpc_httpcli_context *ctx; |
|
|
|
|
} portreq; |
|
|
|
|
|
|
|
|
|
static void got_port_from_server(void *arg, |
|
|
|
@ -138,6 +205,19 @@ static void got_port_from_server(void *arg, |
|
|
|
|
size_t i; |
|
|
|
|
int port = 0; |
|
|
|
|
portreq *pr = arg; |
|
|
|
|
if (!response || response->status != 200) { |
|
|
|
|
grpc_httpcli_request req; |
|
|
|
|
memset(&req, 0, sizeof(req)); |
|
|
|
|
GPR_ASSERT(pr->retries < 10); |
|
|
|
|
pr->retries++; |
|
|
|
|
req.host = pr->server; |
|
|
|
|
req.path = "/get"; |
|
|
|
|
gpr_log(GPR_DEBUG, "failed port pick from server: retrying"); |
|
|
|
|
sleep(1); |
|
|
|
|
grpc_httpcli_get(pr->ctx, &pr->pollset, &req, GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10),
|
|
|
|
|
got_port_from_server, pr); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
GPR_ASSERT(response); |
|
|
|
|
GPR_ASSERT(response->status == 200); |
|
|
|
|
for (i = 0; i < response->body_length; i++) { |
|
|
|
@ -151,11 +231,6 @@ static void got_port_from_server(void *arg, |
|
|
|
|
gpr_mu_unlock(GRPC_POLLSET_MU(&pr->pollset)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void destroy_pollset_and_shutdown(void *p) { |
|
|
|
|
grpc_pollset_destroy(p); |
|
|
|
|
grpc_shutdown(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int pick_port_using_server(char *server) { |
|
|
|
|
grpc_httpcli_context context; |
|
|
|
|
grpc_httpcli_request req; |
|
|
|
@ -167,6 +242,8 @@ static int pick_port_using_server(char *server) { |
|
|
|
|
memset(&req, 0, sizeof(req)); |
|
|
|
|
grpc_pollset_init(&pr.pollset); |
|
|
|
|
pr.port = -1; |
|
|
|
|
pr.server = server; |
|
|
|
|
pr.ctx = &context; |
|
|
|
|
|
|
|
|
|
req.host = server; |
|
|
|
|
req.path = "/get"; |
|
|
|
@ -211,8 +288,9 @@ int grpc_pick_unused_port(void) { |
|
|
|
|
int port = pick_port_using_server(env); |
|
|
|
|
gpr_free(env); |
|
|
|
|
if (port != 0) { |
|
|
|
|
return port; |
|
|
|
|
chose_port(port); |
|
|
|
|
} |
|
|
|
|
return port; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|