blob: 8aa7dba52442daffc5b27f579cb49e7602b6d0b8 [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>
5 * \date 2012
6 */
7/*
8 * Copyright (C) 2012 CESNET
9 *
10 * LICENSE TERMS
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 * 3. Neither the name of the Company nor the names of its contributors
22 * may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 *
25 * ALTERNATIVELY, provided that this notice is retained in full, this
26 * product may be distributed under the terms of the GNU General Public
27 * License (GPL) version 2 or later, in which case the provisions
28 * of the GPL apply INSTEAD OF those given above.
29 *
30 * This software is provided ``as is'', and any express or implied
31 * warranties, including, but not limited to, the implied warranties of
32 * merchantability and fitness for a particular purpose are disclaimed.
33 * In no event shall the company or contributors be liable for any
34 * direct, indirect, incidental, special, exemplary, or consequential
35 * damages (including, but not limited to, procurement of substitute
36 * goods or services; loss of use, data, or profits; or business
37 * interruption) however caused and on any theory of liability, whether
38 * in contract, strict liability, or tort (including negligence or
39 * otherwise) arising in any way out of the use of this software, even
40 * if advised of the possibility of such damage.
41 *
42 */
43
David Kupka1e3e4c82012-09-04 09:32:15 +020044#define _GNU_SOURCE
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020045#include <unistd.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
Tomas Cejkab272bf12012-09-05 16:49:12 +020049#include <err.h>
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020050#include <errno.h>
51#include <sys/types.h>
52#include <sys/socket.h>
53#include <sys/un.h>
54#include <json/json.h>
David Kupka1e3e4c82012-09-04 09:32:15 +020055#include <ctype.h>
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020056
Radek Krejci6cb08982012-07-25 18:01:06 +020057#define SOCKET_FILENAME "/tmp/mod_netconf.sock"
David Kupka1e3e4c82012-09-04 09:32:15 +020058#define BUFFER_SIZE 40960
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020059
60typedef enum MSG_TYPE {
61 REPLY_OK,
62 REPLY_DATA,
63 REPLY_ERROR,
Radek Krejci9e04c7b2012-07-26 15:54:25 +020064 REPLY_INFO,
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020065 MSG_CONNECT,
66 MSG_DISCONNECT,
67 MSG_GET,
68 MSG_GETCONFIG,
69 MSG_EDITCONFIG,
70 MSG_COPYCONFIG,
71 MSG_DELETECONFIG,
72 MSG_LOCK,
73 MSG_UNLOCK,
Radek Krejci9e04c7b2012-07-26 15:54:25 +020074 MSG_KILL,
Radek Krejci80c10d92012-07-30 08:38:50 +020075 MSG_INFO,
76 MSG_GENERIC
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020077} MSG_TYPE;
78
79void print_help(char* progname)
80{
81 printf("Usage: %s <command>\n", progname);
82 printf("Available commands:\n");
83 printf("\tconnect\n");
84 printf("\tdisconnect\n");
85 printf("\tcopy-config\n");
86 printf("\tdelete-config\n");
87 printf("\tedit-config\n");
88 printf("\tget\n");
89 printf("\tget-config\n");
90 printf("\tkill-session\n");
91 printf("\tlock\n");
92 printf("\tunlock\n");
Radek Krejci9e04c7b2012-07-26 15:54:25 +020093 printf("\tinfo\n");
Radek Krejci80c10d92012-07-30 08:38:50 +020094 printf("\tgeneric\n");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +020095}
96
Tomas Cejkab272bf12012-09-05 16:49:12 +020097/**
98 * \brief Get multiline input text.
99 *
100 * Print given prompt and read text ending with CTRL+D.
101 * Output string is terminated by 0. Ending '\n' is removed.
102 *
103 * On error, err is called!
104 *
105 * \param[out] output - pointer to memory where string is stored
106 * \param[out] size - size of string return by getdelim()
107 * \param[in] prompt - text printed as a prompt
108 */
109void readmultiline(char **output, size_t *size, const char *prompt)
110{
111 printf(prompt);
112 if (getdelim (output, size, 'D' - 0x40, stdin) == -1) {
113 if (errno) {
114 err(errno, "Cannot read input.");
115 }
116 *output = (char *) malloc(sizeof(char));
117 **output = 0;
118 return;
119 }
120 (*output)[(*size)-1] = 0; /* input text end "sanitation" */
121 (*output)[(strlen(*output))-1] = 0; /* input text end "sanitation" */
122}
123
124/**
125 * \brief Get input text.
126 *
127 * Print given prompt and read one line of text.
128 * Output string is terminated by 0. Ending '\n' is removed.
129 *
130 * On error, err is called!
131 *
132 * \param[out] output - pointer to memory where string is stored
133 * \param[out] size - size of string return by getline()
134 * \param[in] prompt - text printed as a prompt
135 */
136void readline(char **output, size_t *size, const char *prompt)
137{
138 printf(prompt);
139 if (getline (output, size, stdin) == -1) {
140 if (errno) {
141 err(errno, "Cannot read input.");
142 }
143 }
144 (*output)[(*size)-1] = 0; /* input text end "sanitation" */
145 (*output)[(strlen(*output))-1] = 0; /* input text end "sanitation" */
146}
147
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200148int main (int argc, char* argv[])
149{
Kupka David00b9c5c2012-09-05 09:45:50 +0200150 json_object* msg = NULL, *reply = NULL, *capabilities = NULL;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200151 const char* msg_text;
152 int sock;
153 struct sockaddr_un addr;
154 size_t len;
David Kupka1e3e4c82012-09-04 09:32:15 +0200155 char *buffer;
156 char* line = NULL, *chunked_msg_text;
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200157 int i, alen;
David Kupka1e3e4c82012-09-04 09:32:15 +0200158 int buffer_size, buffer_len, ret, chunk_len;
159 char c, chunk_len_str[12];
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200160
161 if (argc != 2) {
162 print_help(argv[0]);
163 return (2);
164 }
165
166 /* connect to the daemon */
167 sock = socket(PF_UNIX, SOCK_STREAM, 0);
168 if (sock == -1) {
169 fprintf(stderr, "Creating socket failed (%s)", strerror(errno));
170 return (EXIT_FAILURE);
171 }
172 addr.sun_family = AF_UNIX;
173 strncpy(addr.sun_path, SOCKET_FILENAME, sizeof(addr.sun_path));
174 len = strlen(addr.sun_path) + sizeof(addr.sun_family);
175 if (connect(sock, (struct sockaddr *) &addr, len) == -1) {
176 fprintf(stderr, "Connecting to mod_netconf (%s) failed (%s)", SOCKET_FILENAME, strerror(errno));
177 close(sock);
178 return (EXIT_FAILURE);
179 }
180
181 line = malloc(sizeof(char) * BUFFER_SIZE);
182
183 if (strcmp(argv[1], "connect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200184 /*
185 * create NETCONF session
186 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200187 msg = json_object_new_object();
188 json_object_object_add(msg, "type", json_object_new_int(MSG_CONNECT));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200189 readline(&line, &len, "Hostname:");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200190 json_object_object_add(msg, "host", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200191 readline(&line, &len, "Port:");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200192 json_object_object_add(msg, "port", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200193 readline(&line, &len, "Username:");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200194 json_object_object_add(msg, "user", json_object_new_string(line));
195 printf("Password: ");
196 system("stty -echo");
197 getline (&line, &len, stdin);
198 system("stty echo");
199 printf("\n");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200200 json_object_object_add(msg, "pass", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200201 /* clean read password - it is needless because we have a copy in json... :-( */
202 memset(line, 'X', len);
203 free(line);
204 line = NULL;
205
206 printf("Supported capabilities\n");
207 capabilities = json_object_new_array();
208 json_object_object_add(msg, "capabilities", capabilities);
209 while (1) {
210 readline(&line, &len, "Next capability (empty for end): ");
211 if (strlen(line) == 0) {
212 break;
213 }
214 json_object_array_add (capabilities, json_object_new_string(line));
215 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200216 } else if (strcmp(argv[1], "disconnect") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200217 /*
218 * Close NETCONF session
219 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200220 msg = json_object_new_object();
221 json_object_object_add(msg, "type", json_object_new_int(MSG_DISCONNECT));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200222 readline(&line, &len, "Session: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200223 json_object_object_add(msg, "session", json_object_new_string(line));
224 } else if (strcmp(argv[1], "copy-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200225 /*
226 * NETCONF <copy-config>
227 */
Radek Krejci035bf4e2012-07-25 10:59:09 +0200228 msg = json_object_new_object();
229 json_object_object_add(msg, "type", json_object_new_int(MSG_COPYCONFIG));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200230 readline(&line, &len, "Session: ");
Radek Krejci035bf4e2012-07-25 10:59:09 +0200231 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200232 readline(&line, &len, "Source (running|startup|candidate): ");
Radek Krejciae021c12012-07-25 18:03:52 +0200233 if (strlen(line) > 0) {
234 json_object_object_add(msg, "source", json_object_new_string(line));
235 } else {
Tomas Cejkab272bf12012-09-05 16:49:12 +0200236 readmultiline(&line, &len, "Configuration data (ending with CTRL+D): ");
Radek Krejciae021c12012-07-25 18:03:52 +0200237 json_object_object_add(msg, "config", json_object_new_string(line));
238 }
Tomas Cejkab272bf12012-09-05 16:49:12 +0200239 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejci035bf4e2012-07-25 10:59:09 +0200240 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200241 } else if (strcmp(argv[1], "delete-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200242 /*
243 * NETCONF <delete-config>
244 */
245 msg = json_object_new_object();
246 json_object_object_add(msg, "type", json_object_new_int(MSG_DELETECONFIG));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200247 readline(&line, &len, "Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200248 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200249 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200250 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200251 } else if (strcmp(argv[1], "edit-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200252 /*
253 * NETCONF <edit-config>
254 */
255 msg = json_object_new_object();
256 json_object_object_add(msg, "type", json_object_new_int(MSG_EDITCONFIG));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200257 readline(&line, &len, "Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200258 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200259 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200260 json_object_object_add(msg, "target", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200261 readline(&line, &len, "Default operation (merge|replace|none): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200262 if (strlen(line) > 0) {
263 json_object_object_add(msg, "default-operation", json_object_new_string(line));
264 }
Tomas Cejkab272bf12012-09-05 16:49:12 +0200265 readline(&line, &len, "Error option (stop-on-error|continue-on-error|rollback-on-error): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200266 if (strlen(line) > 0) {
267 json_object_object_add(msg, "error-option", json_object_new_string(line));
268 }
Tomas Cejkab272bf12012-09-05 16:49:12 +0200269 readmultiline(&line, &len, "Configuration data (ending with CTRL+D): ");
Radek Krejcib1e08f42012-07-26 10:54:28 +0200270 json_object_object_add(msg, "config", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200271 } else if (strcmp(argv[1], "get") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200272 /*
273 * NETCONF <get>
274 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200275 msg = json_object_new_object();
276 json_object_object_add(msg, "type", json_object_new_int(MSG_GET));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200277 readline(&line, &len, "Session: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200278 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200279 readmultiline(&line, &len, "Filter (ending with CTRL+D): ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200280 if (strlen(line) > 0) {
281 json_object_object_add(msg, "filter", json_object_new_string(line));
282 }
283 } else if (strcmp(argv[1], "get-config") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200284 /*
285 * NETCONF <get-config>
286 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200287 msg = json_object_new_object();
288 json_object_object_add(msg, "type", json_object_new_int(MSG_GETCONFIG));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200289 readline(&line, &len, "Session: ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200290 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200291 readline(&line, &len, "Source (running|startup|candidate): ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200292 json_object_object_add(msg, "source", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200293 readmultiline(&line, &len, "Filter (ending with CTRL+D): ");
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200294 if (strlen(line) > 0) {
295 json_object_object_add(msg, "filter", json_object_new_string(line));
296 }
297 } else if (strcmp(argv[1], "kill-session") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200298 /*
299 * NETCONF <kill-session>
300 */
301 msg = json_object_new_object();
302 json_object_object_add(msg, "type", json_object_new_int(MSG_KILL));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200303 readline(&line, &len, "Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200304 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200305 readline(&line, &len, "Kill session with ID: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200306 json_object_object_add(msg, "session-id", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200307 } else if (strcmp(argv[1], "lock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200308 /*
309 * NETCONF <lock>
310 */
311 msg = json_object_new_object();
312 json_object_object_add(msg, "type", json_object_new_int(MSG_LOCK));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200313 readline(&line, &len, "Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200314 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200315 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200316 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200317 } else if (strcmp(argv[1], "unlock") == 0) {
Radek Krejciaa422df2012-07-25 18:04:59 +0200318 /*
319 * NETCONF <unlock>
320 */
321 msg = json_object_new_object();
322 json_object_object_add(msg, "type", json_object_new_int(MSG_UNLOCK));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200323 readline(&line, &len,"Session: ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200324 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200325 readline(&line, &len, "Target (running|startup|candidate): ");
Radek Krejciaa422df2012-07-25 18:04:59 +0200326 json_object_object_add(msg, "target", json_object_new_string(line));
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200327 } else if (strcmp(argv[1], "info") == 0) {
328 /*
329 * Get information about NETCONF session
330 */
331 msg = json_object_new_object();
332 json_object_object_add(msg, "type", json_object_new_int(MSG_INFO));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200333 readline(&line, &len, "Session: ");
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200334 json_object_object_add(msg, "session", json_object_new_string(line));
Radek Krejci80c10d92012-07-30 08:38:50 +0200335 } else if (strcmp(argv[1], "generic") == 0) {
336 /*
337 * Generic NETCONF request
338 */
339 msg = json_object_new_object();
340 json_object_object_add(msg, "type", json_object_new_int(MSG_GENERIC));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200341 readline(&line, &len, "Session: ");
Radek Krejci80c10d92012-07-30 08:38:50 +0200342 json_object_object_add(msg, "session", json_object_new_string(line));
Tomas Cejkab272bf12012-09-05 16:49:12 +0200343 readmultiline(&line, &len, "NETCONF <rpc> content (ending with CTRL+D): ");
Radek Krejci80c10d92012-07-30 08:38:50 +0200344 json_object_object_add(msg, "content", json_object_new_string(line));
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200345 } else {
Radek Krejciaa422df2012-07-25 18:04:59 +0200346 /*
347 * Unknown request
348 */
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200349 fprintf(stderr, "Unknown command %s\n", argv[1]);
350 close(sock);
351 return (EXIT_FAILURE);
352 }
353
354 /* send the message */
355 if (msg != NULL) {
356 msg_text = json_object_to_json_string(msg);
David Kupka1e3e4c82012-09-04 09:32:15 +0200357 asprintf (&chunked_msg_text, "\n#%d\n%s\n##\n", (int)strlen(msg_text), msg_text);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200358
Radek Krejci035bf4e2012-07-25 10:59:09 +0200359 if (json_object_object_get(msg, "pass") == NULL) {
360 /* print message only if it does not contain password */
361 printf("Sending: %s\n", msg_text);
362 }
David Kupka1e3e4c82012-09-04 09:32:15 +0200363 send(sock, chunked_msg_text, strlen(chunked_msg_text) + 1, 0);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200364
365 json_object_put(msg);
David Kupka1e3e4c82012-09-04 09:32:15 +0200366 free (chunked_msg_text);
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200367 } else {
368 close(sock);
369 return (EXIT_FAILURE);
370 }
371
David Kupka1e3e4c82012-09-04 09:32:15 +0200372 /* read json in chunked framing */
373 buffer_size = 0;
374 buffer_len = 0;
375 buffer = NULL;
376 while (1) {
377 /* read chunk length */
378 if ((ret = recv (sock, &c, 1, 0)) != 1 || c != '\n') {
379 free (buffer);
380 buffer = NULL;
381 break;
382 }
383 if ((ret = recv (sock, &c, 1, 0)) != 1 || c != '#') {
384 free (buffer);
385 buffer = NULL;
386 break;
387 }
388 i=0;
389 memset (chunk_len_str, 0, 12);
390 while ((ret = recv (sock, &c, 1, 0) == 1 && (isdigit(c) || c == '#'))) {
391 if (i==0 && c == '#') {
392 if (recv (sock, &c, 1, 0) != 1 || c != '\n') {
393 /* end but invalid */
394 free (buffer);
395 buffer = NULL;
396 }
397 /* end of message, double-loop break */
398 goto msg_complete;
399 }
400 chunk_len_str[i++] = c;
401 }
402 if (c != '\n') {
403 free (buffer);
404 buffer = NULL;
405 break;
406 }
407 if ((chunk_len = atoi (chunk_len_str)) == 0) {
408 free (buffer);
409 buffer = NULL;
410 break;
411 }
412 buffer_size += chunk_len+1;
413 buffer = realloc (buffer, sizeof(char)*buffer_size);
414 if ((ret = recv (sock, buffer+buffer_len, chunk_len, 0)) == -1 || ret != chunk_len) {
415 free (buffer);
416 buffer = NULL;
417 break;
418 }
419 buffer_len += ret;
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200420 }
David Kupka1e3e4c82012-09-04 09:32:15 +0200421msg_complete:
422
423 if (buffer != NULL) {
424 reply = json_tokener_parse(buffer);
425 free (buffer);
426 } else {
427 reply = NULL;
428 }
429
Radek Krejci035bf4e2012-07-25 10:59:09 +0200430 printf("Received:\n");
431 if (reply == NULL) {
432 printf("(null)\n");
433 } else {
434 json_object_object_foreach(reply, key, value) {
435 printf("Key: %s, Value: ", key);
436 switch (json_object_get_type(value)) {
437 case json_type_string:
438 printf("%s\n", json_object_get_string(value));
439 break;
440 case json_type_int:
441 printf("%d\n", json_object_get_int(value));
442 break;
Radek Krejci9e04c7b2012-07-26 15:54:25 +0200443 case json_type_array:
444 printf("\n");
445 alen = json_object_array_length(value);
446 for (i = 0; i < alen; i++) {
447 printf("\t(%d) %s\n", i, json_object_get_string(json_object_array_get_idx(value, i)));
448 }
449 break;
Radek Krejci035bf4e2012-07-25 10:59:09 +0200450 default:
451 printf("\n");
452 break;
453 }
454 }
455 json_object_put(reply);
456 }
Radek Krejci8fd1f5e2012-07-24 17:33:36 +0200457 close(sock);
458 free(line);
459
460 return (EXIT_SUCCESS);
461}