diff options
author | dormando <dormando@rydia.net> | 2022-08-08 23:27:20 -0700 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2022-08-24 22:32:40 -0700 |
commit | 4c919bd2e7eae0cc436c62780fd6294f028b3525 (patch) | |
tree | 6324ce196cc28fc5a6373d1db229180f55accc6c /memcached.c | |
parent | 6bcc5b8553d43f494e85ab3ec2ce789c38a3ca33 (diff) | |
download | memcached-4c919bd2e7eae0cc436c62780fd6294f028b3525.tar.gz |
core: allow forcing protocol per listener socket
-l proto[ascii]:127.0.0.1:11211
accepts:
- ascii
- binary
- negotiating
- proxy
Allows running proxy on default listeners but direct to memcached on a
specific port, or binary and ascii on different ports, or etc.
Diffstat (limited to 'memcached.c')
-rw-r--r-- | memcached.c | 64 |
1 files changed, 54 insertions, 10 deletions
diff --git a/memcached.c b/memcached.c index 1ee5205..c9084f8 100644 --- a/memcached.c +++ b/memcached.c @@ -647,7 +647,8 @@ void conn_io_queue_return(io_pending_t *io) { conn *conn_new(const int sfd, enum conn_states init_state, const int event_flags, const int read_buffer_size, enum network_transport transport, - struct event_base *base, void *ssl, uint64_t conntag) { + struct event_base *base, void *ssl, uint64_t conntag, + enum protocol bproto) { conn *c; assert(sfd >= 0 && sfd < max_fds); @@ -693,7 +694,7 @@ conn *conn_new(const int sfd, enum conn_states init_state, } c->transport = transport; - c->protocol = settings.binding_protocol; + c->protocol = bproto; c->tag = conntag; /* unix socket mode doesn't need this, so zeroed out. but why @@ -3073,7 +3074,7 @@ static void drive_machine(conn *c) { #endif dispatch_conn_new(sfd, conn_new_cmd, EV_READ | EV_PERSIST, - READ_BUFFER_CACHED, c->transport, ssl_v, c->tag); + READ_BUFFER_CACHED, c->transport, ssl_v, c->tag, c->protocol); } stop = true; @@ -3474,7 +3475,8 @@ static int server_socket(const char *interface, int port, enum network_transport transport, FILE *portnumber_file, bool ssl_enabled, - uint64_t conntag) { + uint64_t conntag, + enum protocol bproto) { int sfd; struct linger ling = {0, 0}; struct addrinfo *ai; @@ -3616,12 +3618,12 @@ static int server_socket(const char *interface, } dispatch_conn_new(per_thread_fd, conn_read, EV_READ | EV_PERSIST, - UDP_READ_BUFFER_SIZE, transport, NULL, conntag); + UDP_READ_BUFFER_SIZE, transport, NULL, conntag, bproto); } } else { if (!(listen_conn_add = conn_new(sfd, conn_listening, EV_READ | EV_PERSIST, 1, - transport, main_base, NULL, conntag))) { + transport, main_base, NULL, conntag, bproto))) { fprintf(stderr, "failed to create listening connection\n"); exit(EXIT_FAILURE); } @@ -3652,7 +3654,7 @@ static int server_sockets(int port, enum network_transport transport, #endif if (settings.inter == NULL) { - return server_socket(settings.inter, port, transport, portnumber_file, ssl_enabled, conntag); + return server_socket(settings.inter, port, transport, portnumber_file, ssl_enabled, conntag, settings.binding_protocol); } else { // tokenize them and bind to each one of them.. char *b; @@ -3683,8 +3685,50 @@ static int server_sockets(int port, enum network_transport transport, } #endif + // Allow forcing the protocol of this listener. + const char *protostr = "proto"; + enum protocol bproto = settings.binding_protocol; + if (strncmp(p, protostr, strlen(protostr)) == 0) { + p += strlen(protostr); + if (*p == '[') { + char *e = strchr(p, ']'); + if (e == NULL) { + fprintf(stderr, "Invalid protocol spec: \"%s\"\n", p); + free(list); + return 1; + } + char *st = ++p; // skip '['; + *e = '\0'; + size_t len = e - st; + p = ++e; // skip ']' + p++; // skip an assumed ':' + + if (strncmp(st, "ascii", len) == 0) { + bproto = ascii_prot; + } else if (strncmp(st, "binary", len) == 0) { + bproto = binary_prot; + } else if (strncmp(st, "negotiating", len) == 0) { + bproto = negotiating_prot; + } else if (strncmp(st, "proxy", len) == 0) { +#ifdef PROXY + if (settings.proxy_enabled) { + bproto = proxy_prot; + } else { + fprintf(stderr, "Proxy must be enabled to use: \"%s\"\n", list); + free(list); + return 1; + } +#else + fprintf(stderr, "Server not built with proxy: \"%s\"\n", list); + free(list); + return 1; +#endif + } + } + } + const char *tagstr = "tag"; - if (strncmp(p, "tag", strlen(tagstr)) == 0) { + if (strncmp(p, tagstr, strlen(tagstr)) == 0) { p += strlen(tagstr); if (*p == '[') { char *e = strchr(p, ']'); @@ -3750,7 +3794,7 @@ static int server_sockets(int port, enum network_transport transport, if (strcmp(p, "*") == 0) { p = NULL; } - ret |= server_socket(p, the_port, transport, portnumber_file, ssl_enabled, conntag); + ret |= server_socket(p, the_port, transport, portnumber_file, ssl_enabled, conntag, bproto); if (ret != 0 && errno_save == 0) errno_save = errno; } free(list); @@ -3830,7 +3874,7 @@ static int server_socket_unix(const char *path, int access_mask) { } if (!(listen_conn = conn_new(sfd, conn_listening, EV_READ | EV_PERSIST, 1, - local_transport, main_base, NULL, 0))) { + local_transport, main_base, NULL, 0, settings.binding_protocol))) { fprintf(stderr, "failed to create listening connection\n"); exit(EXIT_FAILURE); } |