From 1ba52b3daa6bf7f581baf82e1d2793cf8d5444fa Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Thu, 11 Jun 2015 20:49:59 +1000 Subject: [PATCH] Round robin over the redirect URLs in redirector mode, keeping clients from the same IP on the same URL --- src/connector.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/connector.c b/src/connector.c index d73d9d0f..46142cc4 100644 --- a/src/connector.c +++ b/src/connector.c @@ -26,6 +26,7 @@ typedef struct client_instance client_instance_t; typedef struct sender_send sender_send_t; typedef struct share share_t; +typedef struct redirect redirect_t; struct client_instance { /* For clients hashtable */ @@ -83,6 +84,13 @@ struct share { int64_t id; }; +struct redirect { + UT_hash_handle hh; + char address_name[INET6_ADDRSTRLEN]; + int id; + int redirect_no; +}; + /* Private data for the connector */ struct connector_data { ckpool_t *ckp; @@ -125,6 +133,11 @@ struct connector_data { /* For protecting the pending sends list */ mutex_t sender_lock; pthread_cond_t sender_cond; + + /* Hash list of all redirected IP address in redirector mode */ + redirect_t *redirects; + /* What redirect we're currently up to */ + int redirect; }; typedef struct connector_data cdata_t; @@ -707,15 +720,41 @@ static void *sender(void *arg) return NULL; } +static int add_redirect(ckpool_t *ckp, cdata_t *cdata, client_instance_t *client) +{ + redirect_t *redirect; + bool found; + + ck_wlock(&cdata->lock); + HASH_FIND_STR(cdata->redirects, client->address_name, redirect); + if (!redirect) { + redirect = ckzalloc(sizeof(redirect_t)); + strcpy(redirect->address_name, client->address_name); + redirect->redirect_no = cdata->redirect++; + if (cdata->redirect >= ckp->redirecturls) + cdata->redirect = 0; + HASH_ADD_STR(cdata->redirects, address_name, redirect); + found = false; + } else + found = true; + ck_wunlock(&cdata->lock); + + LOGNOTICE("Redirecting client %"PRId64" from %s IP %s to redirecturl %d", + client->id, found ? "matching" : "new", client->address_name, redirect->redirect_no); + return redirect->redirect_no; +} + static void redirect_client(ckpool_t *ckp, client_instance_t *client) { sender_send_t *sender_send; cdata_t *cdata = ckp->data; json_t *val; char *buf; + int num; + num = add_redirect(ckp, cdata, client); JSON_CPACK(val, "{sosss[ssi]}", "id", json_null(), "method", "client.reconnect", - "params", ckp->redirecturl[0], ckp->redirectport[0], 0); + "params", ckp->redirecturl[num], ckp->redirectport[num], 0); buf = json_dumps(val, JSON_EOL); json_decref(val);