Fix for poorly terminated hostname.
[awesomized/libmemcached] / lib / memcached_hosts.c
1 #include <memcached.h>
2 #include "common.h"
3
4 /* Protoypes (static) */
5 static memcached_return server_add(memcached_st *ptr, char *hostname,
6 unsigned int port,
7 memcached_connection type);
8
9 static void host_reset(memcached_server_st *host, char *new_hostname, unsigned int port,
10 memcached_connection type)
11 {
12 memset(host, 0, sizeof(memcached_server_st));
13 host->hostname= new_hostname;
14 host->port= port;
15 host->fd= -1;
16 host->type= type;
17 host->read_ptr= host->read_buffer;
18 host->write_ptr= host->write_buffer;
19 }
20
21 memcached_return memcached_server_push(memcached_st *ptr, memcached_server_st *list)
22 {
23 unsigned int x;
24 unsigned int count;
25 memcached_server_st *new_host_list;
26
27 if (!list)
28 return MEMCACHED_SUCCESS;
29
30 for (count= 0; list[count].hostname; count++);
31
32 new_host_list=
33 (memcached_server_st *)realloc(ptr->hosts,
34 sizeof(memcached_server_st) * (count + ptr->number_of_hosts + 1));
35
36 if (!new_host_list)
37 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
38
39 ptr->hosts= new_host_list;
40
41 for (x= 0; list[x].hostname; x++)
42 {
43 ptr->hosts[ptr->number_of_hosts].hostname= strdup(list[x].hostname);
44 ptr->hosts[ptr->number_of_hosts].port= list[x].port;
45 ptr->hosts[ptr->number_of_hosts].fd= list[x].fd;
46 ptr->hosts[ptr->number_of_hosts].stack_responses= list[x].stack_responses;
47 ptr->hosts[ptr->number_of_hosts].cursor_active= list[x].cursor_active;
48 ptr->hosts[ptr->number_of_hosts].type= list[x].type;
49 ptr->number_of_hosts++;
50 }
51 host_reset(&ptr->hosts[ptr->number_of_hosts], NULL, 0,
52 MEMCACHED_CONNECTION_UNKNOWN);
53
54 return MEMCACHED_SUCCESS;
55 }
56
57 memcached_return memcached_server_add_unix_socket(memcached_st *ptr, char *filename)
58 {
59 if (!filename)
60 return MEMCACHED_FAILURE;
61
62 return server_add(ptr, filename, 0, MEMCACHED_CONNECTION_UNIX_SOCKET);
63 }
64
65 memcached_return memcached_server_add_udp(memcached_st *ptr,
66 char *hostname,
67 unsigned int port)
68 {
69 if (!port)
70 port= MEMCACHED_DEFAULT_PORT;
71
72 if (!hostname)
73 hostname= "localhost";
74
75 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_UDP);
76 }
77
78 memcached_return memcached_server_add(memcached_st *ptr,
79 char *hostname,
80 unsigned int port)
81 {
82 if (!port)
83 port= MEMCACHED_DEFAULT_PORT;
84
85 if (!hostname)
86 hostname= "localhost";
87
88 return server_add(ptr, hostname, port, MEMCACHED_CONNECTION_TCP);
89 }
90
91 static memcached_return server_add(memcached_st *ptr, char *hostname,
92 unsigned int port,
93 memcached_connection type)
94 {
95 memcached_server_st *new_host_list;
96 char *new_hostname;
97 LIBMEMCACHED_MEMCACHED_SERVER_ADD_START();
98
99
100 if (ptr->number_of_hosts)
101 {
102 new_host_list= (memcached_server_st *)realloc(ptr->hosts,
103 sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
104 if (!new_host_list)
105 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
106 host_reset(&new_host_list[ptr->number_of_hosts], NULL, 0,
107 MEMCACHED_CONNECTION_UNKNOWN);
108 }
109 else
110 {
111 new_host_list=
112 (memcached_server_st *)malloc(sizeof(memcached_server_st) * 2);
113 if (!new_host_list)
114 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
115 host_reset(&new_host_list[0], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN);
116 host_reset(&new_host_list[1], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN);
117 }
118
119 ptr->hosts= new_host_list;
120
121 new_hostname=
122 (char *)malloc(sizeof(char) * (strlen(hostname)+1));
123
124 if (!new_hostname)
125 return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
126
127 memcpy(new_hostname, hostname, strlen(hostname));
128 new_hostname[strlen(hostname)]= 0;
129 host_reset(&ptr->hosts[ptr->number_of_hosts], new_hostname, port, type);
130 ptr->number_of_hosts++;
131
132 LIBMEMCACHED_MEMCACHED_SERVER_ADD_END();
133
134 return MEMCACHED_SUCCESS;
135 }
136
137 memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
138 char *hostname, unsigned int port,
139 memcached_return *error)
140 {
141 unsigned int count;
142 memcached_server_st *new_host_list;
143 char *new_hostname;
144
145 if (!hostname)
146 return ptr;
147
148 if (!port)
149 port= MEMCACHED_DEFAULT_PORT;
150
151 /* Always count so that we keep a free host at the end */
152 if (ptr)
153 {
154 for (count= 0; ptr[count].hostname; count++);
155 count+= 2;
156 new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
157 if (!new_host_list)
158 goto error;
159 host_reset(&new_host_list[count-1], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN);
160 }
161 else
162 {
163 count= 2;
164 new_host_list= (memcached_server_st *)malloc(sizeof(memcached_server_st) * count);
165 if (!new_host_list)
166 goto error;
167 host_reset(&new_host_list[0], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN);
168 host_reset(&new_host_list[1], NULL, 0, MEMCACHED_CONNECTION_UNKNOWN);
169 }
170
171 new_hostname= strdup(hostname);
172
173 if (!new_hostname)
174 goto error;
175
176 host_reset(&new_host_list[count-2], new_hostname, port, MEMCACHED_CONNECTION_TCP);
177
178 *error= MEMCACHED_SUCCESS;
179 return new_host_list;
180 error:
181 *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
182
183 return NULL;
184 }
185
186 unsigned int memcached_server_list_count(memcached_server_st *ptr)
187 {
188 unsigned int x;
189
190 for (x= 0; ptr[x].hostname; x++);
191
192 return x;
193 }
194
195 void memcached_server_list_free(memcached_server_st *ptr)
196 {
197 unsigned int x;
198
199 for (x= 0; ptr[x].hostname; x++)
200 free(ptr[x].hostname);
201
202 free(ptr);
203 }