blob: 42c554952d81e27ba087a6c06563a3981406382f [file] [log] [blame]
Radek Krejci8fd1f5e2012-07-24 17:33:36 +02001/*!
2 * \file test-client.c
3 * \brief Testing client sending JSON requsts to the mod_netconf socket
4 * \author Radek Krejci <rkrejci@cesnet.cz>
Tomas Cejka94da2c52013-01-08 18:20:30 +01005 * \author Tomas Cejka <cejkat@cesnet.cz>
Radek Krejci8fd1f5e2012-07-24 17:33:36 +02006 * \date 2012
Tomas Cejka94da2c52013-01-08 18:20:30 +01007 * \date 2013
Radek Krejci8fd1f5e2012-07-24 17:33:36 +02008 */
9/*
10 * Copyright (C) 2012 CESNET
11 *
12 * LICENSE TERMS
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in
21 * the documentation and/or other materials provided with the
22 * distribution.
23 * 3. Neither the name of the Company nor the names of its contributors
24 * may be used to endorse or promote products derived from this
25 * software without specific prior written permission.
26 *
27 * ALTERNATIVELY, provided that this notice is retained in full, this
28 * product may be distributed under the terms of the GNU General Public
29 * License (GPL) version 2 or later, in which case the provisions
30 * of the GPL apply INSTEAD OF those given above.
31 *
32 * This software is provided ``as is'', and any express or implied
33 * warranties, including, but not limited to, the implied warranties of
34 * merchantability and fitness for a particular purpose are disclaimed.
35 * In no event shall the company or contributors be liable for any
36 * direct, indirect, incidental, special, exemplary, or consequential
37 * damages (including, but not limited to, procurement of substitute
38 * goods or services; loss of use, data, or profits; or business
39 * interruption) however caused and on any theory of liability, whether
40 * in contract, strict liability, or tort (including negligence or
41 * otherwise) arising in any way out of the use of this software, even
42 * if advised of the possibility of such damage.
43 *
44 */
45
David Kupka1e3e4c82012-09-04 09:32:15 +020046#define _GNU_SOURCE
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020047#include <unistd.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
Tomas Cejkab272bf12012-09-05 16:49:12 +020051#include <err.h>
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020052#include <errno.h>
53#include <sys/types.h>
54#include <sys/socket.h>
55#include <sys/un.h>
56#include <json/json.h>
David Kupka1e3e4c82012-09-04 09:32:15 +020057#include <ctype.h>
Tomas Cejka94da2c52013-01-08 18:20:30 +010058#include "message_type.h"
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020059
Radek Krejci6cb08982012-07-25 18:01:06 +020060#define SOCKET_FILENAME "/tmp/mod_netconf.sock"
David Kupka1e3e4c82012-09-04 09:32:15 +020061#define BUFFER_SIZE 40960
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020062
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020063void print_help(char* progname)
64{
65 printf("Usage: %s <command>\n", progname);
66 printf("Available commands:\n");
67 printf("\tconnect\n");
68 printf("\tdisconnect\n");
69 printf("\tcopy-config\n");
70 printf("\tdelete-config\n");
71 printf("\tedit-config\n");
72 printf("\tget\n");
73 printf("\tget-config\n");
74 printf("\tkill-session\n");
75 printf("\tlock\n");
76 printf("\tunlock\n");
Radek Krejci9e04c7b2012-07-26 15:54:25 +020077 printf("\tinfo\n");
Radek Krejci80c10d92012-07-30 08:38:50 +020078 printf("\tgeneric\n");
Tomas Cejka94da2c52013-01-08 18:20:30 +010079 printf("\tgetschema\n");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020080}
81
Tomas Cejkab272bf12012-09-05 16:49:12 +020082/**
83 * \brief Get multiline input text.
84 *
85 * Print given prompt and read text ending with CTRL+D.
86 * Output string is terminated by 0. Ending '\n' is removed.
87 *
88 * On error, err is called!
89 *
90 * \param[out] output - pointer to memory where string is stored
91 * \param[out] size - size of string return by getdelim()
92 * \param[in] prompt - text printed as a prompt
93 */
94void readmultiline(char **output, size_t *size, const char *prompt)
95{
96 printf(prompt);
97 if (getdelim (output, size, 'D' - 0x40, stdin) == -1) {
98 if (errno) {
99 err(errno, "Cannot read input.");
100 }
101 *output = (char *) malloc(sizeof(char));
102 **output = 0;
103 return;
104 }
105 (*output)[(*size)-1] = 0; /* input text end "sanitation" */
106 (*output)[(strlen(*output))-1] = 0; /* input text end "sanitation" */
107}
108
109/**
110 * \brief Get input text.
111 *
112 * Print given prompt and read one line of text.
113 * Output string is terminated by 0. Ending '\n' is removed.
114 *
115 * On error, err is called!
116 *
117 * \param[out] output - pointer to memory where string is stored
118 * \param[out] size - size of string return by getline()
119 * \param[in] prompt - text printed as a prompt
120 */
121void readline(char **output, size_t *size, const char *prompt)
122{
123 printf(prompt);
124 if (getline (output, size, stdin) == -1) {
125 if (errno) {
126 err(errno, "Cannot read input.");
127 }
128 }
129 (*output)[(*size)-1] = 0; /* input text end "sanitation" */
130 (*output)[(strlen(*output))-1] = 0; /* input text end "sanitation" */
131}
132
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200133int main (int argc, char* argv[])
134{
Kupka David00b9c5c2012-09-05 09:45:50 +0200135 json_object* msg = NULL, *reply = NULL, *capabilities = NULL;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200136 const char* msg_text;
137 int sock;
138 struct sockaddr_un addr;
139 size_t len;
David Kupka1e3e4c82012-09-04 09:32:15 +0200140 char *buffer;
141 char* line = NULL, *chunked_msg_text;
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200142 int i, alen;
David Kupka1e3e4c82012-09-04 09:32:15 +0200143 int buffer_size, buffer_len, ret, chunk_len;
144 char c, chunk_len_str[12];
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200145
146 if (argc != 2) {
147 print_help(argv[0]);
148 return (2);
149 }
150
151 /* connect to the daemon */
152 sock = socket(PF_UNIX, SOCK_STREAM, 0);
153 if (sock == -1) {
154 fprintf(stderr, "Creating socket failed (%s)", strerror(errno));
155 return (EXIT_FAILURE);
156 }
157 addr.sun_family = AF_UNIX;
158 strncpy(addr.sun_path, SOCKET_FILENAME, sizeof(addr.sun_path));
159 len = strlen(addr.sun_path) + sizeof(addr.sun_family);
160 if (connect(sock, (struct sockaddr *) &addr, len) == -1) {
161 fprintf(stderr, "Connecting to mod_netconf (%s) failed (%s)", SOCKET_FILENAME, strerror(errno));
162 close(sock);
163 return (EXIT_FAILURE);
164 }
165
166 line = malloc(sizeof(char) * BUFFER_SIZE);
167
168 if (strcmp(argv[1], "connect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200169 /*
170 * create NETCONF session
171 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200172 msg = json_object_new_object();
173 json_object_object_add(msg, "type", json_object_new_int(MSG_CONNECT));
Tomas Cejka42434462012-09-05 18:11:43 +0200174 readline(&line, &len, "Hostname: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200175 json_object_object_add(msg, "host", json_object_new_string(line));
Tomas Cejka42434462012-09-05 18:11:43 +0200176 readline(&line, &len, "Port: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200177 json_object_object_add(msg, "port", json_object_new_string(line));
Tomas Cejka42434462012-09-05 18:11:43 +0200178 readline(&line, &len, "Username: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200179 json_object_object_add(msg, "user", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200180 system("stty -echo");
Tomas Cejka42434462012-09-05 18:11:43 +0200181 readline(&line, &len, "Password: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200182 system("stty echo");
183 printf("\n");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200184 json_object_object_add(msg, "pass", json_object_new_string(line));
Tomas Cejka42434462012-09-05 18:11:43 +0200185
Tomas Cejkab272bf12012-09-05 16:49:12 +0200186 /* clean read password - it is needless because we have a copy in json... :-( */
187 memset(line, 'X', len);
188 free(line);
189 line = NULL;
190
191 printf("Supported capabilities\n");
192 capabilities = json_object_new_array();
193 json_object_object_add(msg, "capabilities", capabilities);
194 while (1) {
195 readline(&line, &len, "Next capability (empty for end): ");
196 if (strlen(line) == 0) {
197 break;
198 }
199 json_object_array_add (capabilities, json_object_new_string(line));
200 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200201 } else if (strcmp(argv[1], "disconnect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200202 /*
203 * Close NETCONF session
204 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200205 msg = json_object_new_object();
206 json_object_object_add(msg, "type", json_object_new_int(MSG_DISCONNECT));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200207 readline(&line, &len, "Session: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200208 json_object_object_add(msg, "session", json_object_new_string(line));
209 } else if (strcmp(argv[1], "copy-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200210 /*
211 * NETCONF <copy-config>
212 */
Radek Krejci035bf4e2012-07-25 10:59:09 +0200213 msg = json_object_new_object();
214 json_object_object_add(msg, "type", json_object_new_int(MSG_COPYCONFIG));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200215 readline(&line, &len, "Session: ");
Radek Krejci035bf4e2012-07-25 10:59:09 +0200216 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200217 readline(&line, &len, "Source (running|startup|candidate): ");
Radek Krejciae021c12012-07-25 18:03:52 +0200218 if (strlen(line) > 0) {
219 json_object_object_add(msg, "source", json_object_new_string(line));
220 } else {
Tomas Cejkab272bf12012-09-05 16:49:12 +0200221 readmultiline(&line, &len, "Configuration data (ending with CTRL+D): ");
Radek Krejciae021c12012-07-25 18:03:52 +0200222 json_object_object_add(msg, "config", json_object_new_string(line));
223 }
Tomas Cejkab272bf12012-09-05 16:49:12 +0200224 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejci035bf4e2012-07-25 10:59:09 +0200225 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200226 } else if (strcmp(argv[1], "delete-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200227 /*
228 * NETCONF <delete-config>
229 */
230 msg = json_object_new_object();
231 json_object_object_add(msg, "type", json_object_new_int(MSG_DELETECONFIG));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200232 readline(&line, &len, "Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200233 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200234 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200235 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200236 } else if (strcmp(argv[1], "edit-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200237 /*
238 * NETCONF <edit-config>
239 */
240 msg = json_object_new_object();
241 json_object_object_add(msg, "type", json_object_new_int(MSG_EDITCONFIG));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200242 readline(&line, &len, "Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200243 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200244 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200245 json_object_object_add(msg, "target", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200246 readline(&line, &len, "Default operation (merge|replace|none): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200247 if (strlen(line) > 0) {
248 json_object_object_add(msg, "default-operation", json_object_new_string(line));
249 }
Tomas Cejkab272bf12012-09-05 16:49:12 +0200250 readline(&line, &len, "Error option (stop-on-error|continue-on-error|rollback-on-error): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200251 if (strlen(line) > 0) {
252 json_object_object_add(msg, "error-option", json_object_new_string(line));
253 }
Tomas Cejkab272bf12012-09-05 16:49:12 +0200254 readmultiline(&line, &len, "Configuration data (ending with CTRL+D): ");
Radek Krejcib1e08f42012-07-26 10:54:28 +0200255 json_object_object_add(msg, "config", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200256 } else if (strcmp(argv[1], "get") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200257 /*
258 * NETCONF <get>
259 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200260 msg = json_object_new_object();
261 json_object_object_add(msg, "type", json_object_new_int(MSG_GET));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200262 readline(&line, &len, "Session: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200263 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200264 readmultiline(&line, &len, "Filter (ending with CTRL+D): ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200265 if (strlen(line) > 0) {
266 json_object_object_add(msg, "filter", json_object_new_string(line));
267 }
268 } else if (strcmp(argv[1], "get-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200269 /*
270 * NETCONF <get-config>
271 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200272 msg = json_object_new_object();
273 json_object_object_add(msg, "type", json_object_new_int(MSG_GETCONFIG));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200274 readline(&line, &len, "Session: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200275 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200276 readline(&line, &len, "Source (running|startup|candidate): ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200277 json_object_object_add(msg, "source", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200278 readmultiline(&line, &len, "Filter (ending with CTRL+D): ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200279 if (strlen(line) > 0) {
280 json_object_object_add(msg, "filter", json_object_new_string(line));
281 }
282 } else if (strcmp(argv[1], "kill-session") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200283 /*
284 * NETCONF <kill-session>
285 */
286 msg = json_object_new_object();
287 json_object_object_add(msg, "type", json_object_new_int(MSG_KILL));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200288 readline(&line, &len, "Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200289 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200290 readline(&line, &len, "Kill session with ID: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200291 json_object_object_add(msg, "session-id", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200292 } else if (strcmp(argv[1], "lock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200293 /*
294 * NETCONF <lock>
295 */
296 msg = json_object_new_object();
297 json_object_object_add(msg, "type", json_object_new_int(MSG_LOCK));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200298 readline(&line, &len, "Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200299 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200300 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200301 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200302 } else if (strcmp(argv[1], "unlock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200303 /*
304 * NETCONF <unlock>
305 */
306 msg = json_object_new_object();
307 json_object_object_add(msg, "type", json_object_new_int(MSG_UNLOCK));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200308 readline(&line, &len,"Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200309 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200310 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200311 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200312 } else if (strcmp(argv[1], "info") == 0) {
313 /*
314 * Get information about NETCONF session
315 */
316 msg = json_object_new_object();
317 json_object_object_add(msg, "type", json_object_new_int(MSG_INFO));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200318 readline(&line, &len, "Session: ");
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200319 json_object_object_add(msg, "session", json_object_new_string(line));
Radek Krejci80c10d92012-07-30 08:38:50 +0200320 } else if (strcmp(argv[1], "generic") == 0) {
321 /*
322 * Generic NETCONF request
323 */
324 msg = json_object_new_object();
325 json_object_object_add(msg, "type", json_object_new_int(MSG_GENERIC));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200326 readline(&line, &len, "Session: ");
Radek Krejci80c10d92012-07-30 08:38:50 +0200327 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200328 readmultiline(&line, &len, "NETCONF <rpc> content (ending with CTRL+D): ");
Radek Krejci80c10d92012-07-30 08:38:50 +0200329 json_object_object_add(msg, "content", json_object_new_string(line));
Tomas Cejka94da2c52013-01-08 18:20:30 +0100330 } else if (strcmp(argv[1], "getschema") == 0) {
331 /*
332 * Get information about NETCONF session
333 */
334 msg = json_object_new_object();
335 json_object_object_add(msg, "type", json_object_new_int(MSG_GETSCHEMA));
336 readline(&line, &len, "Session: ");
337 json_object_object_add(msg, "session", json_object_new_string(line));
338 readline(&line, &len, "Identificator: ");
339 json_object_object_add(msg, "identifier", json_object_new_string(line));
340 readline(&line, &len, "Format [YIN]: ");
341 json_object_object_add(msg, "format", json_object_new_string(line));
342 readline(&line, &len, "Version: ");
343 json_object_object_add(msg, "version", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200344 } else {
Radek Krejciaa422df2012-07-25 18:04:59 +0200345 /*
346 * Unknown request
347 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200348 fprintf(stderr, "Unknown command %s\n", argv[1]);
349 close(sock);
350 return (EXIT_FAILURE);
351 }
352
353 /* send the message */
354 if (msg != NULL) {
355 msg_text = json_object_to_json_string(msg);
David Kupka1e3e4c82012-09-04 09:32:15 +0200356 asprintf (&chunked_msg_text, "\n#%d\n%s\n##\n", (int)strlen(msg_text), msg_text);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200357
Radek Krejci035bf4e2012-07-25 10:59:09 +0200358 if (json_object_object_get(msg, "pass") == NULL) {
359 /* print message only if it does not contain password */
360 printf("Sending: %s\n", msg_text);
361 }
David Kupka1e3e4c82012-09-04 09:32:15 +0200362 send(sock, chunked_msg_text, strlen(chunked_msg_text) + 1, 0);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200363
364 json_object_put(msg);
David Kupka1e3e4c82012-09-04 09:32:15 +0200365 free (chunked_msg_text);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200366 } else {
367 close(sock);
368 return (EXIT_FAILURE);
369 }
370
David Kupka1e3e4c82012-09-04 09:32:15 +0200371 /* read json in chunked framing */
372 buffer_size = 0;
373 buffer_len = 0;
374 buffer = NULL;
375 while (1) {
376 /* read chunk length */
377 if ((ret = recv (sock, &c, 1, 0)) != 1 || c != '\n') {
378 free (buffer);
379 buffer = NULL;
380 break;
381 }
382 if ((ret = recv (sock, &c, 1, 0)) != 1 || c != '#') {
383 free (buffer);
384 buffer = NULL;
385 break;
386 }
387 i=0;
388 memset (chunk_len_str, 0, 12);
389 while ((ret = recv (sock, &c, 1, 0) == 1 && (isdigit(c) || c == '#'))) {
390 if (i==0 && c == '#') {
391 if (recv (sock, &c, 1, 0) != 1 || c != '\n') {
392 /* end but invalid */
393 free (buffer);
394 buffer = NULL;
395 }
396 /* end of message, double-loop break */
397 goto msg_complete;
398 }
399 chunk_len_str[i++] = c;
400 }
401 if (c != '\n') {
402 free (buffer);
403 buffer = NULL;
404 break;
405 }
406 if ((chunk_len = atoi (chunk_len_str)) == 0) {
407 free (buffer);
408 buffer = NULL;
409 break;
410 }
411 buffer_size += chunk_len+1;
412 buffer = realloc (buffer, sizeof(char)*buffer_size);
413 if ((ret = recv (sock, buffer+buffer_len, chunk_len, 0)) == -1 || ret != chunk_len) {
414 free (buffer);
415 buffer = NULL;
416 break;
417 }
418 buffer_len += ret;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200419 }
David Kupka1e3e4c82012-09-04 09:32:15 +0200420msg_complete:
421
422 if (buffer != NULL) {
423 reply = json_tokener_parse(buffer);
424 free (buffer);
425 } else {
426 reply = NULL;
427 }
428
Radek Krejci035bf4e2012-07-25 10:59:09 +0200429 printf("Received:\n");
430 if (reply == NULL) {
431 printf("(null)\n");
432 } else {
433 json_object_object_foreach(reply, key, value) {
434 printf("Key: %s, Value: ", key);
435 switch (json_object_get_type(value)) {
436 case json_type_string:
437 printf("%s\n", json_object_get_string(value));
438 break;
439 case json_type_int:
440 printf("%d\n", json_object_get_int(value));
441 break;
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200442 case json_type_array:
443 printf("\n");
444 alen = json_object_array_length(value);
445 for (i = 0; i < alen; i++) {
446 printf("\t(%d) %s\n", i, json_object_get_string(json_object_array_get_idx(value, i)));
447 }
448 break;
Radek Krejci035bf4e2012-07-25 10:59:09 +0200449 default:
450 printf("\n");
451 break;
452 }
453 }
454 json_object_put(reply);
455 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200456 close(sock);
457 free(line);
458
459 return (EXIT_SUCCESS);
460}