rsstats 0.0.1
Redis Enterprise Statistic collector
clustercon.c
Go to the documentation of this file.
1
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include "clustercon.h"
26#include "base64.h" /* Base64 encoder and decoder */
27
28#include <unistd.h>
29#include <string.h>
30#ifdef _WIN32
31#include <winsock2.h>
32#include <ws2tcpip.h>
33#else
34#include <arpa/inet.h>
35#endif
36#include <openssl/err.h>
37
39 rsclustercon_t* rsclustercon = NULL;
40
41 if (NULL==(rsclustercon=malloc(sizeof(struct rsclustercon_s)))) {
42 perror("cluster_new");
43 return NULL;
44 }
45 if (NULL==(rsclustercon->host=strdup(cluster->host))) {
46 perror("cluster_new host");
47 free(rsclustercon);
48 return NULL;
49 }
50 if (NULL==(rsclustercon->user=strdup(cluster->user))) {
51 perror("cluster_new user");
52 free(rsclustercon->host);
53 free(rsclustercon);
54 return NULL;
55 }
56 if (NULL==(rsclustercon->pass=strdup(cluster->pass))) {
57 perror("cluster_new pass");
58 free(rsclustercon->user);
59 free(rsclustercon->host);
60 free(rsclustercon);
61 return NULL;
62 }
63 if (NULL==(rsclustercon->cacert=strdup(cluster->cacert))) {
64 perror("cluster_new cacert");
65 free(rsclustercon->pass);
66 free(rsclustercon->user);
67 free(rsclustercon->host);
68 free(rsclustercon);
69 return NULL;
70 }
71 rsclustercon->insecure = strcmp(cluster->insecure,"false");
72 return rsclustercon;
73}
74
75int cluster_open(rsclustercon_t* rsclustercon) {
76 struct sockaddr_in server_addr;
77
78 /* Socket creation */
79 rsclustercon->sock = socket(AF_INET, SOCK_STREAM, 0);
80 if (rsclustercon->sock < 0) {
81 perror("Socket creation error");
82 return 1;
83 }
84
85 server_addr.sin_family = AF_INET;
86 server_addr.sin_port = htons(9443);
87 if (inet_pton(AF_INET, rsclustercon->host, &server_addr.sin_addr) <= 0) {
88 perror("Invalid address");
89 return 2;
90 }
91
92 /* Server connection */
93 if (connect(rsclustercon->sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) != 0) {
94 perror("Connection failed");
95 return 3;
96 }
97
98 /* OpenSSL initialization */
99 SSL_library_init();
100 /* OpenSSL_add_all_algorithms(); */
101 OpenSSL_add_ssl_algorithms();
102 SSL_load_error_strings();
103
104 /* Initialize OpenSSL context */
105 rsclustercon->ctx = SSL_CTX_new(SSLv23_client_method());
106 if (!rsclustercon->ctx) {
107 ERR_print_errors_fp(stderr);
108 return 4;
109 }
110
111 /* Load server certificate or certificate from a certification authority (CA) */
112 if (strcmp("",rsclustercon->cacert)&&rsclustercon->insecure==0)
113 if (SSL_CTX_load_verify_locations(rsclustercon->ctx, rsclustercon->cacert, NULL) != 1) {
114 ERR_print_errors_fp(stderr);
115 return 5;
116 }
117
118 if (rsclustercon->insecure)
119 /* Disable certificat check */
120 SSL_CTX_set_verify(rsclustercon->ctx, SSL_VERIFY_NONE, NULL);
121 else
122 /* Enable certificat check */
123 SSL_CTX_set_verify(rsclustercon->ctx, SSL_VERIFY_PEER, NULL);
124
125
126 /* Link SSL configuration to the socket */
127 rsclustercon->ssl = SSL_new(rsclustercon->ctx);
128 SSL_set_fd(rsclustercon->ssl, rsclustercon->sock);
129
130 /* Initiate SSL connection */
131 if (SSL_connect(rsclustercon->ssl) <= 0) {
132 ERR_print_errors_fp(stderr);
133 return 6;
134 }
135
136 return 0;
137}
138
139cJSON* cluster_queryget(const rsclustercon_t* rsclustercon, const char* endpoint) {
140 char buf[1024];
141
142 /* Prepare basic authentication */
143 char* auth_encoded;
144 {
145 char* auth_clear;
146 if (NULL==(auth_clear = (char*)malloc(strlen(rsclustercon->user)+1+strlen(rsclustercon->pass)+1))) {
147 perror("cluster_queryget malloc(auth)");
148 return NULL;
149 };
150 strcpy(auth_clear,rsclustercon->user);
151 strcat(auth_clear,":");
152 strcat(auth_clear,rsclustercon->pass);
153 auth_encoded=base64_encode(auth_clear);
154 free(auth_clear);
155 }
156
157 /* Prepare query */
158 char http_request[512];
159 snprintf(http_request, sizeof(http_request),
160 "GET %s HTTP/1.1\r\n"
161 "Host: %s\r\n"
162 "Content-Type: application/json\r\n"
163 "Authorization: Basic %s\r\n"
164 "Connection: close\r\n\r\n",
165 endpoint,rsclustercon->host,auth_encoded
166 );
167 free(auth_encoded);
168
169 /* Send query */
170 SSL_write(rsclustercon->ssl, http_request, strlen(http_request));
171
172 /* Read reply */
173 int bytes=0;
174 char* reply=NULL;
175 if (NULL==(reply=strdup(""))) {
176 perror("cluster_queryget strdup");
177 return NULL;
178 };
179 while ((bytes=SSL_read(rsclustercon->ssl, buf, 1024 - 1)) > 0) {
180 buf[bytes] = 0;
181 char* newreply;
182 if ((newreply=(char*)realloc(reply,strlen(reply)+bytes+1))==NULL) {
183 perror("Unable to allocate reply buffer");
184 free(reply);
185 return NULL;
186 } else
187 reply = newreply;
188 strcat(reply, buf);
189 }
190
191 /* Remove HTTP headers */
192 char* http_body;
193 char* retval_txt;
194 if (NULL==(http_body = strstr(reply,"\r\n\r\n")))
195 retval_txt= NULL;
196 else
197 retval_txt=strdup(http_body);
198 free(reply);
199
200 cJSON* retval_json = cJSON_Parse(retval_txt);
201 free(retval_txt);
202
203 return retval_json;
204}
205
206void cluster_close(rsclustercon_t* rsclustercon) {
207 SSL_shutdown(rsclustercon->ssl);
208 SSL_free(rsclustercon->ssl);
209 close(rsclustercon->sock);
210 SSL_CTX_free(rsclustercon->ctx);
211 EVP_cleanup();
212}
213
214void cluster_del(rsclustercon_t* rsclustercon) {
215 free(rsclustercon->cacert);
216 free(rsclustercon->pass);
217 free(rsclustercon->user);
218 free(rsclustercon->host);
219 free(rsclustercon);
220}
221
222/* vim: set tw=80: */
char * base64_encode(char *plain)
Encode a zero terminated C string in Base64.
Definition: base64.c:39
Simple Base64 encoding and decoding functions.
void cluster_close(rsclustercon_t *rsclustercon)
Definition: clustercon.c:206
void cluster_del(rsclustercon_t *rsclustercon)
Definition: clustercon.c:214
rsclustercon_t * cluster_new(const cluster_t *cluster)
Definition: clustercon.c:38
int cluster_open(rsclustercon_t *rsclustercon)
Definition: clustercon.c:75
cJSON * cluster_queryget(const rsclustercon_t *rsclustercon, const char *endpoint)
Definition: clustercon.c:139
<+DETAILED+>
#define NULL
Definition: rsstats-opts.c:64
Definition: cJSON.h:103
char * host
Definition: cluster.h:26
char * insecure
Definition: cluster.h:29
char * pass
Definition: cluster.h:28
char * user
Definition: cluster.h:27
char * cacert
Definition: cluster.h:30
unsigned short int insecure
Definition: clustercon.h:33
char * cacert
Definition: clustercon.h:34
SSL_CTX * ctx
Definition: clustercon.h:36