accept [IPv6] on memcached_servers_parse
[awesomized/libmemcached] / src / libmemcached / parse.cc
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #include "libmemcached/common.h"
17
18 memcached_server_list_st memcached_servers_parse(const char *server_strings) {
19 char *string;
20 const char *begin_ptr;
21 const char *end_ptr;
22 memcached_server_st *servers = NULL;
23 memcached_return_t rc;
24
25 WATCHPOINT_ASSERT(server_strings);
26
27 end_ptr = server_strings + strlen(server_strings);
28
29 for (begin_ptr = server_strings, string = (char *) strchr(server_strings, ',');
30 begin_ptr != end_ptr; string = (char *) strchr(begin_ptr, ','))
31 {
32 char buffer[HUGE_STRING_LEN];
33 char *ptr, *ptr2;
34 uint32_t weight = 0;
35
36 if (string) {
37 memcpy(buffer, begin_ptr, (size_t)(string - begin_ptr));
38 buffer[(unsigned int) (string - begin_ptr)] = 0;
39 begin_ptr = string + 1;
40 } else {
41 size_t length = strlen(begin_ptr);
42 memcpy(buffer, begin_ptr, length);
43 buffer[length] = 0;
44 begin_ptr = end_ptr;
45 }
46
47 ptr = strchr(buffer, '[');
48 if (ptr) {
49 ptr2 = strchr(ptr+1, ']');
50 }
51 if (ptr && ptr2) {
52 // [IPv6]:port
53 ptr = strchr(ptr2+1, ':');
54 } else {
55 // IPv4:port or name:port
56 ptr = strchr(buffer, ':');
57 }
58 in_port_t port = 0;
59 if (ptr) {
60 ptr[0] = 0;
61
62 ptr++;
63
64 errno = 0;
65 port = (in_port_t) strtoul(ptr, (char **) NULL, 10);
66 if (errno) {
67 memcached_server_free(servers);
68 return NULL;
69 }
70
71 ptr2 = strchr(ptr, ' ');
72 if (!ptr2)
73 ptr2 = strchr(ptr, ':');
74
75 if (ptr2) {
76 ptr2++;
77 errno = 0;
78 weight = uint32_t(strtoul(ptr2, (char **) NULL, 10));
79 if (errno) {
80 memcached_server_free(servers);
81 return NULL;
82 }
83 }
84 }
85
86 servers = memcached_server_list_append_with_weight(servers, buffer, port, weight, &rc);
87
88 if (isspace(*begin_ptr)) {
89 begin_ptr++;
90 }
91 }
92
93 return servers;
94 }