1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 #include "config.h"
3 
4 #include <memcached/protocol_binary.h>
5 #include <memcached/openssl.h>
6 #include <platform/platform.h>
7 
8 #include <getopt.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 
12 #include "programs/utilities.h"
13 
14 
get_response(BIO *bio, protocol_binary_response_no_extras *res)15 static void *get_response(BIO *bio, protocol_binary_response_no_extras *res) {
16     uint32_t vallen;
17 
18     ensure_recv(bio, res, sizeof(*res));
19     vallen = ntohl(res->message.header.response.bodylen);
20 
21     if (vallen == 0) {
22         return NULL;
23     } else {
24         void *buffer = malloc(vallen);
25         cb_assert(buffer != NULL);
26         ensure_recv(bio, buffer, vallen);
27         return buffer;
28     }
29 }
30 
store(BIO *bio, const void *key, uint16_t nkey, const void *bytes, uint32_t nbytes)31 static void store(BIO *bio,
32                   const void *key,
33                   uint16_t nkey,
34                   const void *bytes,
35                   uint32_t nbytes)
36 {
37     protocol_binary_request_set request;
38     protocol_binary_response_no_extras response;
39     void *payload;
40 
41     memset(&request, 0, sizeof(request));
42     request.message.header.request.magic = PROTOCOL_BINARY_REQ;
43     request.message.header.request.opcode = PROTOCOL_BINARY_CMD_SET;
44     request.message.header.request.keylen = htons((uint16_t)nkey);
45     request.message.header.request.extlen = 8;
46     request.message.header.request.bodylen = htonl(nkey + 8 + nbytes);
47 
48     ensure_send(bio, &request, sizeof(request.bytes));
49     ensure_send(bio, key, nkey);
50     ensure_send(bio, bytes, nbytes);
51     if (BIO_flush(bio) != 1) {
52         fprintf(stderr, "Failed to flush bio instance\n");
53         exit(EXIT_FAILURE);
54     }
55 
56     payload = get_response(bio, &response);
57     free(payload);
58     cb_assert(ntohs(response.message.header.response.status) == PROTOCOL_BINARY_RESPONSE_SUCCESS);
59 }
60 
fetch(BIO *bio, const void *key, uint16_t nkey)61 static char * fetch(BIO *bio,
62                   const void *key,
63                   uint16_t nkey)
64 {
65     protocol_binary_request_get request;
66     protocol_binary_response_no_extras response;
67     char *payload;
68 
69     memset(&request, 0, sizeof(request));
70     request.message.header.request.magic = PROTOCOL_BINARY_REQ;
71     request.message.header.request.opcode = PROTOCOL_BINARY_CMD_GET;
72     request.message.header.request.keylen = htons((uint16_t)nkey);
73     request.message.header.request.bodylen = htonl(nkey);
74 
75     ensure_send(bio, &request, sizeof(request.bytes));
76     ensure_send(bio, key, nkey);
77     if (BIO_flush(bio) != 1) {
78         fprintf(stderr, "Failed to flush bio instance\n");
79         exit(EXIT_FAILURE);
80     }
81 
82     payload = get_response(bio, &response);
83     cb_assert(ntohs(response.message.header.response.status) == PROTOCOL_BINARY_RESPONSE_SUCCESS);
84     cb_assert(payload != NULL);
85     return payload;
86 
87 }
88 
89 
do_ssl_test(BIO *bio)90 static void do_ssl_test(BIO *bio)
91 {
92     uint32_t datalen = 512*1024;
93     void *data = malloc(datalen);
94     char *rcv = NULL;
95     const char *key = "Hello World";
96     int ii;
97 
98     for (ii = 0; ii < 1024; ++ii) {
99         fprintf(stdout, "%u\n", ii);
100         store(bio, key, (uint16_t)strlen(key), data, datalen);
101         rcv = fetch(bio, key, (uint16_t)strlen(key));
102         cb_assert(memcmp(data, rcv + 4, datalen) == 0);
103         free(rcv);
104     }
105 }
106 
main(int argc, char** argv)107 int main(int argc, char** argv) {
108     int cmd;
109     const char *port = "11210";
110     const char *host = "localhost";
111     const char *user = NULL;
112     const char *pass = NULL;
113     int secure = 0;
114     char *ptr;
115     SSL_CTX* ctx;
116     BIO* bio;
117 
118     /* Initialize the socket subsystem */
119     cb_initialize_sockets();
120 
121     while ((cmd = getopt(argc, argv, "h:p:u:P:s")) != EOF) {
122         switch (cmd) {
123         case 'h' :
124             host = optarg;
125             ptr = strchr(optarg, ':');
126             if (ptr != NULL) {
127                 *ptr = '\0';
128                 port = ptr + 1;
129             }
130             break;
131         case 'p':
132             port = optarg;
133             break;
134         case 'u' :
135             user = optarg;
136             break;
137         case 'P':
138             pass = optarg;
139             break;
140         case 's':
141             secure = 1;
142             break;
143         default:
144             fprintf(stderr,
145                     "Usage ssltest [-h host[:port]] [-p port] [-u user] [-p pass] [-s]\n");
146             return 1;
147         }
148     }
149 
150     if (create_ssl_connection(&ctx, &bio, host, port, user, pass, secure) != 0) {
151         return 1;
152     }
153 
154     do_ssl_test(bio);
155 
156     BIO_free_all(bio);
157     if (secure) {
158         SSL_CTX_free(ctx);
159     }
160 
161     return EXIT_SUCCESS;
162 }
163