Permalink
Browse files

Substitute localhost marker in the JSON

This marker might appear since server release 2.5 as part of CCCP

More info:
* http://review.couchbase.org/29996
* http://review.couchbase.org/30067

Change-Id: Ib888ce6985961266532a3561253aa0633505d9c7
Reviewed-on: http://review.couchbase.org/30834
Reviewed-by: Trond Norbye <trond.norbye@gmail.com>
Tested-by: Trond Norbye <trond.norbye@gmail.com>
  • Loading branch information...
avsej authored and trondn committed Dec 4, 2013
1 parent 56bc1cf commit ae1fca03cd98b99380fe90650cd079ce85e4d342
Showing with 87 additions and 8 deletions.
  1. +17 −0 include/libvbucket/vbucket.h
  2. +70 −8 src/vbucket.c
@@ -125,6 +125,23 @@ extern "C" {
vbucket_source_t data_source,
const char *data);
+ /**
+ * Parse a vbucket configuration and substitute local address if needed
+ * @param handle the vbucket config handle to store the result
+ * @param data_source what kind of datasource to parse
+ * @param data A zero terminated string representing the data to parse.
+ * For LIBVBUCKET_SOURCE_FILE this is the file to parse,
+ * for LIBVBUCKET_SOURCE_MEMORY it is the actual JSON body.
+ * @param peername a string, representing address of local peer
+ * (usually 127.0.0.1)
+ * @return 0 for success, the appropriate error code otherwise
+ */
+ LIBVBUCKET_PUBLIC_API
+ int vbucket_config_parse2(VBUCKET_CONFIG_HANDLE handle,
+ vbucket_source_t data_source,
+ const char *data,
+ const char *peername);
+
LIBVBUCKET_PUBLIC_API
const char *vbucket_get_error_message(VBUCKET_CONFIG_HANDLE handle);
View
@@ -18,7 +18,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
#include <errno.h>
#include "cJSON.h"
@@ -63,6 +62,8 @@ struct vbucket_config_st {
struct server_st *servers;
struct vbucket_st *fvbuckets;
struct vbucket_st *vbuckets;
+ const char *localhost; /* replacement for $HOST placeholder */
+ size_t nlocalhost;
};
static char *errstr = NULL;
@@ -140,6 +141,28 @@ void vbucket_config_destroy(VBUCKET_CONFIG_HANDLE vb) {
free(vb);
}
+static char *substitute_localhost_marker(struct vbucket_config_st *vb, char *input)
+{
+ char *placeholder;
+ char *result = input;
+ size_t ninput = strlen(input);
+ if (vb->localhost && (placeholder = strstr(input, "$HOST"))) {
+ size_t nprefix = placeholder - input;
+ size_t off = 0;
+ result = calloc(ninput + vb->nlocalhost - 5, sizeof(char));
+ if (!result) {
+ return NULL;
+ }
+ memcpy(result, input, nprefix);
+ off += nprefix;
+ memcpy(result + off, vb->localhost, vb->nlocalhost);
+ off += vb->nlocalhost;
+ memcpy(result + off, input + nprefix + 5, ninput - (nprefix + 5));
+ free(input);
+ }
+ return result;
+}
+
static int populate_servers(struct vbucket_config_st *vb, cJSON *c) {
int i;
@@ -161,15 +184,22 @@ static int populate_servers(struct vbucket_config_st *vb, cJSON *c) {
vb->errmsg = strdup("Failed to allocate storage for server string");
return -1;
}
+ server = substitute_localhost_marker(vb, server);
+ if (server == NULL) {
+ vb->errmsg = strdup("Failed to allocate storage for server string during $HOST substitution");
+ return -1;
+ }
vb->servers[i].authority = server;
}
return 0;
}
-static int get_node_authority(struct vbucket_config_st *vb, cJSON *node, char *buf, size_t nbuf) {
+static int get_node_authority(struct vbucket_config_st *vb, cJSON *node, char **out, size_t nbuf)
+{
cJSON *json;
char *hostname = NULL, *colon = NULL;
int port = -1;
+ char *buf = *out;
json = cJSON_GetObjectItem(node, "hostname");
if (json == NULL || json->type != cJSON_String) {
@@ -196,6 +226,12 @@ static int get_node_authority(struct vbucket_config_st *vb, cJSON *node, char *b
}
snprintf(colon, 7, ":%d", port);
+ buf = substitute_localhost_marker(vb, buf);
+ if (buf == NULL) {
+ vb->errmsg = strdup("Failed to allocate storage for authority string during $HOST substitution");
+ return -1;
+ }
+ *out = buf;
return 0;
}
@@ -208,7 +244,7 @@ static int lookup_server_struct(struct vbucket_config_st *vb, cJSON *c) {
vb->errmsg = strdup("Failed to allocate storage for authority string");
return -1;
}
- if (get_node_authority(vb, c, authority, MAX_AUTHORITY_SIZE) < 0) {
+ if (get_node_authority(vb, c, &authority, MAX_AUTHORITY_SIZE) < 0) {
free(authority);
return -1;
}
@@ -244,6 +280,11 @@ static int update_server_info(struct vbucket_config_st *vb, cJSON *config) {
vb->errmsg = strdup("Failed to allocate storage for couchApiBase string");
return -1;
}
+ value = substitute_localhost_marker(vb, value);
+ if (value == NULL) {
+ vb->errmsg = strdup("Failed to allocate storage for hostname string during $HOST substitution");
+ return -1;
+ }
vb->servers[idx].couchdb_api_base = value;
}
json = cJSON_GetObjectItem(node, "hostname");
@@ -253,6 +294,11 @@ static int update_server_info(struct vbucket_config_st *vb, cJSON *config) {
vb->errmsg = strdup("Failed to allocate storage for hostname string");
return -1;
}
+ value = substitute_localhost_marker(vb, value);
+ if (value == NULL) {
+ vb->errmsg = strdup("Failed to allocate storage for hostname string during $HOST substitution");
+ return -1;
+ }
vb->servers[idx].rest_api_authority = value;
}
json = cJSON_GetObjectItem(node, "thisNode");
@@ -410,7 +456,7 @@ static int parse_ketama_config(VBUCKET_CONFIG_HANDLE vb, cJSON *config)
vb->errmsg = strdup("Failed to allocate storage for node authority");
return -1;
}
- if (get_node_authority(vb, node, buf, MAX_AUTHORITY_SIZE) < 0) {
+ if (get_node_authority(vb, node, &buf, MAX_AUTHORITY_SIZE) < 0) {
return -1;
}
vb->servers[ii].authority = buf;
@@ -424,6 +470,11 @@ static int parse_ketama_config(VBUCKET_CONFIG_HANDLE vb, cJSON *config)
vb->errmsg = strdup("Failed to allocate storage for hostname string");
return -1;
}
+ buf = substitute_localhost_marker(vb, buf);
+ if (buf == NULL) {
+ vb->errmsg = strdup("Failed to allocate storage for hostname string during $HOST substitution");
+ return -1;
+ }
vb->servers[ii].rest_api_authority = buf;
}
qsort(vb->servers, vb->num_servers, sizeof(struct server_st), server_cmp);
@@ -475,7 +526,8 @@ static int parse_cjson(VBUCKET_CONFIG_HANDLE handle, cJSON *config)
return 0;
}
-static int parse_from_memory(VBUCKET_CONFIG_HANDLE handle, const char *data) {
+static int parse_from_memory(VBUCKET_CONFIG_HANDLE handle, const char *data)
+{
int ret;
cJSON *c = cJSON_Parse(data);
if (c == NULL) {
@@ -559,17 +611,27 @@ VBUCKET_CONFIG_HANDLE vbucket_config_create(void)
return calloc(1, sizeof(struct vbucket_config_st));
}
-int vbucket_config_parse(VBUCKET_CONFIG_HANDLE handle,
- vbucket_source_t data_source,
- const char *data)
+int vbucket_config_parse2(VBUCKET_CONFIG_HANDLE handle,
+ vbucket_source_t data_source,
+ const char *data,
+ const char *peername)
{
+ handle->localhost = peername;
+ handle->nlocalhost = peername ? strlen(peername) : 0;
if (data_source == LIBVBUCKET_SOURCE_FILE) {
return parse_from_file(handle, data);
} else {
return parse_from_memory(handle, data);
}
}
+int vbucket_config_parse(VBUCKET_CONFIG_HANDLE handle,
+ vbucket_source_t data_source,
+ const char *data)
+{
+ return vbucket_config_parse2(handle, data_source, data, "localhost");
+}
+
const char *vbucket_get_error_message(VBUCKET_CONFIG_HANDLE handle)
{
return handle->errmsg;

0 comments on commit ae1fca0

Please sign in to comment.