binrpc_api.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2006 iptelorg GmbH
  5. *
  6. * This file is part of ser, a free SIP server.
  7. *
  8. * ser is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * For a license to use the ser software under conditions
  14. * other than those described here, or to purchase support for this
  15. * software, please contact iptel.org by e-mail at the following addresses:
  16. * [email protected]
  17. *
  18. * ser is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program; if not, write to the Free Software
  25. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  26. */
  27. /*
  28. * send commands using binrpc
  29. *
  30. * History:
  31. * --------
  32. * 2006-11-09 created by vlada
  33. * 2006-12-20 extended by tma
  34. */
  35. #include <sys/types.h>
  36. #include <sys/uio.h>
  37. #include <stdlib.h> /* realloc, rand ... */
  38. #include <stdio.h>
  39. #include <unistd.h>
  40. #include <errno.h>
  41. #include <ctype.h> /* isprint */
  42. #include <time.h> /* time */
  43. /* #include <stropts.h> - is this really needed? --andrei */
  44. #include "../../modules/ctl/ctl_defaults.h" /* default socket & port */
  45. #include "../../modules/ctl/init_socks.h"
  46. #include "../../modules/ctl/binrpc.c" /* ugly hack */
  47. #include "binrpc_api.h"
  48. #define IOVEC_CNT 20
  49. #define TEXT_BUFF_ALLOC_CHUNK 4096
  50. #define FATAL_ERROR -1
  51. #ifndef NAME
  52. #define NAME "binrpc_api"
  53. #endif
  54. #define binrpc_malloc internal_malloc
  55. #define binrpc_realloc internal_realloc
  56. #define binrpc_free internal_free
  57. #ifndef UNIX_PATH_MAX
  58. #define UNIX_PATH_MAX 108
  59. #endif
  60. #ifndef INT2STR_MAX_LEN
  61. #define INT2STR_MAX_LEN (19+1+1) /* 2^64~= 16*10^18 => 19+1 digits + \0 */
  62. #endif
  63. static void* (*internal_malloc)(size_t size) = malloc;
  64. static void* (*internal_realloc)(void* ptr, size_t size) = realloc;
  65. static void (*internal_free)(void* ptr) = free;
  66. static char binrpc_last_errs[1024] = "";
  67. static int verbose = 0;
  68. char *binrpc_get_last_errs()
  69. {
  70. return binrpc_last_errs;
  71. }
  72. void binrpc_clear_last_err()
  73. {
  74. binrpc_last_errs[0] = '\0';
  75. }
  76. void binrpc_set_mallocs(void* _malloc, void* _realloc, void* _free)
  77. {
  78. internal_malloc = _malloc;
  79. internal_realloc = _realloc;
  80. internal_free = _free;
  81. }
  82. static int gen_cookie()
  83. {
  84. return rand();
  85. }
  86. static void hexdump(unsigned char* buf, int len, int ascii)
  87. {
  88. int r, i;
  89. /* dump it in hex */
  90. for (r=0; r<len; r++){
  91. if ((r) && ((r%16)==0)){
  92. if (ascii){
  93. putchar(' ');
  94. for (i=r-16; i<r; i++){
  95. if (isprint(buf[i]))
  96. putchar(buf[i]);
  97. else
  98. putchar('.');
  99. }
  100. }
  101. putchar('\n');
  102. }
  103. printf("%02x ", buf[r]);
  104. };
  105. if (ascii){
  106. for (i=r;i%16; i++)
  107. printf(" ");
  108. putchar(' ');
  109. for (i=16*(r/16); i<r; i++){
  110. if (isprint(buf[i]))
  111. putchar(buf[i]);
  112. else
  113. putchar('.');
  114. }
  115. }
  116. putchar('\n');
  117. }
  118. /* opens, and connects on a STREAM unix socket
  119. * returns socket fd or -1 on error */
  120. static int connect_unix_sock(char* name, int type, struct sockaddr_un* mysun,
  121. char* reply_socket, char* sock_dir)
  122. {
  123. struct sockaddr_un ifsun;
  124. int s;
  125. int len;
  126. int ret;
  127. int retries;
  128. retries=0;
  129. s=-1;
  130. memset(&ifsun, 0, sizeof (struct sockaddr_un));
  131. len=strlen(name);
  132. if (len>UNIX_PATH_MAX){
  133. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  134. "connect_unix_sock: name too long "
  135. "(%d > %d): %s", len, UNIX_PATH_MAX, name);
  136. goto error;
  137. }
  138. ifsun.sun_family=AF_UNIX;
  139. memcpy(ifsun.sun_path, name, len);
  140. #ifdef HAVE_SOCKADDR_SA_LEN
  141. ifsun.sun_len=len;
  142. #endif
  143. s=socket(PF_UNIX, type, 0);
  144. if (s==-1){
  145. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  146. "connect_unix_sock: cannot create unix socket"
  147. " %s: %s [%d]",
  148. name, strerror(errno), errno);
  149. goto error;
  150. }
  151. if (type==SOCK_DGRAM){
  152. /* we must bind so that we can receive replies */
  153. if (reply_socket==0){
  154. if (sock_dir==0)
  155. sock_dir="/tmp";
  156. retry:
  157. ret=snprintf(mysun->sun_path, UNIX_PATH_MAX, "%s/" NAME "_%d",
  158. sock_dir, rand());
  159. if ((ret<0) ||(ret>=UNIX_PATH_MAX)){
  160. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  161. "connect_unix_sock: buffer overflow while trying to"
  162. "generate unix datagram socket name");
  163. goto error;
  164. }
  165. }else{
  166. if (strlen(reply_socket)>UNIX_PATH_MAX){
  167. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  168. "connect_unix_sock: buffer overflow while trying to"
  169. "use the provided unix datagram socket name (%s)",
  170. reply_socket);
  171. goto error;
  172. }
  173. strcpy(mysun->sun_path, reply_socket);
  174. }
  175. mysun->sun_family=AF_UNIX;
  176. if (bind(s, (struct sockaddr*)&mysun, sizeof(struct sockaddr_un))==-1){
  177. //if (bind(s, mysun, sizeof(mysun))==-1){
  178. if (errno==EADDRINUSE && (reply_socket==0) && (retries < 10)){
  179. retries++;
  180. /* try another one */
  181. goto retry;
  182. }
  183. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  184. "connect_unix_sock: could not bind the unix socket to"
  185. " %s: %s (%d)",
  186. mysun->sun_path, strerror(errno), errno);
  187. goto error;
  188. }
  189. }
  190. if (connect(s, (struct sockaddr *)&ifsun, sizeof(ifsun))==-1){
  191. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  192. "connect_unix_sock: connect(%s): %s [%d]",
  193. name, strerror(errno), errno);
  194. goto error;
  195. }
  196. return s;
  197. error:
  198. if (s!=-1) close(s);
  199. return FATAL_ERROR;
  200. }
  201. static int connect_tcpudp_socket(char* address, int port, int type)
  202. {
  203. struct sockaddr_in addr;
  204. struct hostent* he;
  205. int sock;
  206. sock=-1;
  207. /* resolve destination */
  208. he=gethostbyname(address);
  209. if (he==0){
  210. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  211. "connect_tcpudp_socket: could not resolve %s", address);
  212. goto error;
  213. }
  214. /* open socket*/
  215. addr.sin_family=he->h_addrtype;
  216. addr.sin_port=htons(port);
  217. memcpy(&addr.sin_addr.s_addr, he->h_addr_list[0], he->h_length);
  218. sock = socket(he->h_addrtype, type, 0);
  219. if (sock==-1){
  220. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  221. "connect_tcpudp_socket: socket: %s", strerror(errno));
  222. goto error;
  223. }
  224. if (connect(sock, (struct sockaddr*) &addr, sizeof(struct sockaddr))!=0){
  225. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  226. "connect_tcpudp_socket: connect: %s", strerror(errno));
  227. goto error;
  228. }
  229. return sock;
  230. error:
  231. if (sock!=-1) close(sock);
  232. return FATAL_ERROR;
  233. }
  234. /* on exit cleanup */
  235. static void cleanup(struct sockaddr_un* mysun)
  236. {
  237. if (mysun->sun_path[0] != '\0') {
  238. if (unlink(mysun->sun_path) < 0) {
  239. fprintf(stderr, "ERROR: failed to delete %s: %s\n",
  240. mysun->sun_path, strerror(errno));
  241. }
  242. }
  243. }
  244. int binrpc_open_connection(struct binrpc_handle* handle, char* name, int port, int proto,
  245. char* reply_socket, char* sock_dir)
  246. {
  247. struct sockaddr_un mysun;
  248. binrpc_last_errs[0] = '\0';
  249. binrpc_last_errs[sizeof(binrpc_last_errs)-1] = '\0'; /* snprintf safe terminator */
  250. handle->socket = -1;
  251. handle->buf = NULL;
  252. mysun.sun_path[0] = '\0';
  253. /* init the random number generator */
  254. srand(getpid()+time(0)); /* we don't need very strong random numbers */
  255. if (name == NULL) {
  256. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  257. "open_connection: invalid IP address or socket name");
  258. goto error;
  259. }
  260. handle->proto = proto;
  261. switch(proto) {
  262. case UDP_SOCK:
  263. case TCP_SOCK:
  264. if (port == 0) {
  265. port=DEFAULT_CTL_PORT;
  266. }
  267. handle->sock_type = (proto == UDP_SOCK) ? SOCK_DGRAM : SOCK_STREAM;
  268. if ((handle->socket = connect_tcpudp_socket(name, port, handle->sock_type)) < 0) {
  269. goto error;
  270. }
  271. break;
  272. case UNIXS_SOCK:
  273. case UNIXD_SOCK:
  274. handle->sock_type = (proto == UNIXD_SOCK) ? SOCK_DGRAM : SOCK_STREAM;
  275. if ((handle->socket = connect_unix_sock(name, handle->sock_type, &mysun, reply_socket, sock_dir)) < 0) {
  276. goto error;
  277. }
  278. break;
  279. case UNKNOWN_SOCK:
  280. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  281. "open_connection: Bad socket type for %s\n", name); /*vm zmenit*/
  282. goto error;
  283. }
  284. if (handle->sock_type == SOCK_DGRAM) {
  285. handle->buf_size = 8192; /* max size of datagram, < SSIZE_MAX, TODO: does a platform dependent constant exist ? */
  286. }
  287. else {
  288. handle->buf_size = BINRPC_MAX_HDR_SIZE;
  289. }
  290. handle->buf = binrpc_malloc(handle->buf_size);
  291. if (!handle->buf) {
  292. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  293. "open_connection: not enough memory to allocate buffer. Needed %d bytes", handle->buf_size);
  294. binrpc_close_connection(handle);
  295. }
  296. cleanup(&mysun);
  297. return 0;
  298. error:
  299. cleanup(&mysun);
  300. return FATAL_ERROR;
  301. }
  302. int binrpc_open_connection_url(struct binrpc_handle* handle, char* url) {
  303. static char name[100];
  304. char *c, *c2, *rpl_sock;
  305. int port, proto, i;
  306. handle->socket = -1;
  307. handle->buf = NULL;
  308. /* parse proto:name:port|unixd_sock */
  309. c = url;
  310. if (strncasecmp(c, "udp:", 4) == 0)
  311. proto = UDP_SOCK;
  312. else if (strncasecmp(c, "tcp:", 4) == 0)
  313. proto = TCP_SOCK;
  314. else if (strncasecmp(c, "unix:", 5) == 0 || strncasecmp(c, "unixs:", 6) == 0)
  315. proto = UNIXS_SOCK;
  316. else if (strncasecmp(c, "unixd:", 6) == 0)
  317. proto = UNIXD_SOCK;
  318. else {
  319. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  320. "open_connection_url: bad protocol in '%s'", c);
  321. return FATAL_ERROR;
  322. }
  323. while (*c != ':') c++;
  324. c++;
  325. c2 = strchr(c, ':');
  326. if (!c2)
  327. c2 = c + strlen(c);
  328. if (c2 - c > sizeof(name)-1) {
  329. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  330. "open_connection_url: name is too long '%s'", c);
  331. return FATAL_ERROR;
  332. }
  333. for (i=0; c<c2; c++, i++) {
  334. name[i] = *c;
  335. }
  336. name[i] = '\0';
  337. if (strlen(name) == 0) {
  338. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  339. "open_connection_url: name is not specified in '%s'", url);
  340. return FATAL_ERROR;
  341. }
  342. c = c2;
  343. if (*c == ':') c++;
  344. port = 0;
  345. rpl_sock = NULL;
  346. switch (proto) {
  347. case UNIXD_SOCK:
  348. if (strlen(c) != 0)
  349. rpl_sock = c;
  350. break;
  351. case UNIXS_SOCK:
  352. break;
  353. default:
  354. port = atol(c);
  355. if (port == 0) {
  356. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  357. "open_connection_url: port is not specified in '%s'", url);
  358. return FATAL_ERROR;
  359. }
  360. break;
  361. }
  362. return binrpc_open_connection(handle, name, port, proto, rpl_sock, NULL);
  363. }
  364. void binrpc_close_connection(struct binrpc_handle* handle)
  365. {
  366. if (handle->socket != -1) {
  367. close(handle->socket);
  368. handle->socket = -1;
  369. }
  370. if (handle->buf) {
  371. binrpc_free(handle->buf);
  372. handle->buf = NULL;
  373. }
  374. }
  375. /* returns: -1 on error, number of bytes written on success */
  376. static int send_binrpc_cmd(struct binrpc_handle* handle, struct binrpc_pkt *pkt, int cookie)
  377. {
  378. struct iovec v[IOVEC_CNT];
  379. unsigned char msg_hdr[BINRPC_MAX_HDR_SIZE];
  380. int n;
  381. if ((n=binrpc_build_hdr(BINRPC_REQ, binrpc_pkt_len(pkt), cookie, msg_hdr,
  382. BINRPC_MAX_HDR_SIZE)) < 0) {
  383. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  384. "send_binrpc_cmd: build header error: %s",
  385. binrpc_error(n));
  386. return FATAL_ERROR;
  387. }
  388. v[0].iov_base=msg_hdr;
  389. v[0].iov_len=n;
  390. v[1].iov_base=pkt->body;
  391. v[1].iov_len=binrpc_pkt_len(pkt);
  392. write_again:
  393. if ((n=writev(handle->socket, v, 2))<0){
  394. if (errno==EINTR)
  395. goto write_again;
  396. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  397. "send_binrpc_cmd: send packet failed: %s (%d)", strerror(errno), errno);
  398. return FATAL_ERROR;
  399. }
  400. return n;
  401. }
  402. /* reads the whole reply
  403. * returns < 0 on error, reply size on success + initializes resp_handle */
  404. static int get_reply(struct binrpc_handle *handle,
  405. int cookie,
  406. struct binrpc_response_handle *resp_handle)
  407. {
  408. unsigned char *crt, *hdr_end;
  409. int n, ret, tl;
  410. ret = 0;
  411. resp_handle->reply_buf = NULL;
  412. hdr_end = crt = handle->buf;
  413. do {
  414. n = read(handle->socket, crt, handle->buf_size - (crt-handle->buf));
  415. if (n <= 0){
  416. if (errno==EINTR)
  417. continue;
  418. if (n == 0)
  419. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  420. "get_reply: read unexpected EOF: received %d bytes"
  421. " of reply", (int)(long)(crt - handle->buf));
  422. else
  423. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  424. "get_reply: read reply failed: %s (%d)",
  425. strerror(errno), errno);
  426. return FATAL_ERROR;
  427. }
  428. if (verbose >= 3){
  429. /* dump it in hex */
  430. printf("received %d bytes in reply (@offset %d):\n",
  431. n, (int)(crt-handle->buf));
  432. hexdump(crt, n, 1);
  433. }
  434. crt += n;
  435. hdr_end = binrpc_parse_init(&resp_handle->in_pkt, handle->buf, crt - handle->buf, &ret);
  436. } while (ret == E_BINRPC_MORE_DATA);
  437. if (ret < 0){
  438. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  439. "get_reply: reply parsing error: %s",
  440. binrpc_error(ret));
  441. return FATAL_ERROR;
  442. }
  443. if (verbose>1){
  444. printf("new packet: type %02x, len %d, cookie %02x\n",
  445. resp_handle->in_pkt.type, resp_handle->in_pkt.tlen, resp_handle->in_pkt.cookie);
  446. }
  447. if (resp_handle->in_pkt.cookie!=cookie){
  448. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  449. "get_reply: reply parsing error: "
  450. "cookie doesn't match: sent: %02x, received: %02x",
  451. cookie, resp_handle->in_pkt.cookie);
  452. return FATAL_ERROR;
  453. }
  454. /* we know total size and we can allocate buffer for received data */
  455. tl = resp_handle->in_pkt.tlen;
  456. if (handle->sock_type == SOCK_DGRAM) {
  457. /* we must read all datagram in one read call, otherwise unread part is truncated and lost. Read will block execution */
  458. if (crt - hdr_end < tl) {
  459. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  460. "get_reply: datagram truncated. Received: %ld, Expected: %d.",
  461. (long int)(crt-hdr_end), tl);
  462. return FATAL_ERROR;
  463. }
  464. }
  465. if (crt - hdr_end > tl) {
  466. /* header contains probably data from next message, in case of STREAM it could be unread but it's waste of time */
  467. crt = hdr_end + tl;
  468. }
  469. resp_handle->reply_buf = (unsigned char *) binrpc_malloc(tl);
  470. if (!resp_handle->reply_buf) {
  471. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  472. "get_reply: not enough memory to allocate reply buffer. %d bytes needed.",
  473. resp_handle->in_pkt.tlen);
  474. return FATAL_ERROR;
  475. }
  476. crt = resp_handle->reply_buf + (crt-hdr_end);
  477. memcpy(resp_handle->reply_buf, hdr_end, crt - resp_handle->reply_buf);
  478. tl -= crt - resp_handle->reply_buf;
  479. while (tl > 0) {
  480. n=read(handle->socket, crt, tl);
  481. if (n < 0){
  482. if (errno==EINTR)
  483. continue;
  484. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  485. "get_reply: read reply failed: %s (%d)",
  486. strerror(errno), errno);
  487. binrpc_free(resp_handle->reply_buf);
  488. resp_handle->reply_buf = NULL;
  489. return FATAL_ERROR;
  490. }
  491. if (verbose >= 3){
  492. /* dump it in hex */
  493. printf("received %d bytes in reply (@offset %d):\n",
  494. n, (int)(crt-resp_handle->reply_buf));
  495. hexdump(crt, n, 1);
  496. }
  497. crt += n;
  498. tl -= n;
  499. }
  500. return (int)(crt-resp_handle->reply_buf);
  501. }
  502. int binrpc_send_command_ex(
  503. struct binrpc_handle* handle, struct binrpc_pkt *pkt,
  504. struct binrpc_response_handle *resp_handle)
  505. {
  506. int cookie;
  507. cookie = gen_cookie();
  508. if (send_binrpc_cmd(handle, pkt, cookie) < 0) {
  509. return FATAL_ERROR;
  510. }
  511. /* read reply */
  512. memset(&resp_handle->in_pkt, 0, sizeof(resp_handle->in_pkt));
  513. if (get_reply(handle, cookie, resp_handle) < 0) {
  514. return FATAL_ERROR;
  515. }
  516. /* normal exit */
  517. return 0;
  518. }
  519. static int parse_arg(struct binrpc_val* v, char* arg)
  520. {
  521. int i=0;
  522. double f;
  523. char* tmp;
  524. int len;
  525. f = 0.0;
  526. if (*arg)
  527. i=strtol(arg, &tmp, 10);
  528. else
  529. tmp = 0;
  530. if ((tmp==0) || (*tmp)){
  531. if (*arg)
  532. f=strtod(arg, &tmp);
  533. if ((tmp==0) || (*tmp)){
  534. /* not an int or a float => string */
  535. len=strlen(arg);
  536. if ((len>=2) && (arg[0]=='s') && (arg[1]==':')){
  537. tmp=&arg[2];
  538. len-=2;
  539. }else{
  540. tmp=arg;
  541. }
  542. v->type=BINRPC_T_STR;
  543. v->u.strval.s=tmp;
  544. v->u.strval.len=len;
  545. }else{ /* float */
  546. v->type=BINRPC_T_DOUBLE;
  547. v->u.fval=f;
  548. }
  549. }else{ /* int */
  550. v->type=BINRPC_T_INT;
  551. v->u.intval=i;
  552. }
  553. return 0;
  554. }
  555. /* parse the body into a malloc allocated, binrpc_val array */
  556. int binrpc_send_command(
  557. struct binrpc_handle* handle, char* method, char** args, int arg_count,
  558. struct binrpc_response_handle *resp_handle)
  559. {
  560. struct binrpc_pkt req_pkt;
  561. struct binrpc_val v;
  562. int i, size, res = FATAL_ERROR, ret = 0;
  563. unsigned char *req_buf = NULL;
  564. memset(&resp_handle->in_pkt, 0, sizeof(resp_handle->in_pkt));
  565. if (!method || strlen(method) == 0) {
  566. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  567. "send_command: method name not specified");
  568. goto fail;
  569. }
  570. size = BINRPC_MIN_RECORD_SIZE + 8 + strlen(method) + 1; /*max.possible optional value len */
  571. for (i=0; i<arg_count; i++) {
  572. if (parse_arg(&v, args[i]) < 0)
  573. goto fail;
  574. switch (v.type) {
  575. case BINRPC_T_STR:
  576. size += v.u.strval.len + 1;
  577. break;
  578. case BINRPC_T_INT:
  579. case BINRPC_T_DOUBLE:
  580. size += sizeof(int);
  581. break;
  582. default:
  583. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  584. "BUG: send_command: unexpected value type");
  585. goto fail;
  586. }
  587. size += BINRPC_MIN_RECORD_SIZE + 8;
  588. }
  589. req_buf = binrpc_malloc(size);
  590. if (!req_buf) {
  591. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  592. "send_command: not enough memory to allocate buffer. Needed %d bytes", size);
  593. goto fail;
  594. }
  595. if ((ret = binrpc_init_pkt(&req_pkt, req_buf, size)) < 0) goto fail2;
  596. if ((ret = binrpc_addstr(&req_pkt, method, strlen(method))) < 0) goto fail2;
  597. for (i=0; i<arg_count; i++) {
  598. if (parse_arg(&v, args[i]) < 0)
  599. goto fail;
  600. switch (v.type) {
  601. case BINRPC_T_STR:
  602. if ((ret = binrpc_addstr(&req_pkt, v.u.strval.s, v.u.strval.len)) < 0) goto fail2;
  603. break;
  604. case BINRPC_T_INT:
  605. if ((ret = binrpc_addint(&req_pkt, v.u.intval)) < 0) goto fail2;
  606. break;
  607. case BINRPC_T_DOUBLE:
  608. if ((ret = binrpc_adddouble(&req_pkt, v.u.fval)) < 0) goto fail2;
  609. break;
  610. default:
  611. break;
  612. }
  613. }
  614. if (binrpc_send_command_ex(handle, &req_pkt, resp_handle) < 0) {
  615. goto fail;
  616. }
  617. res = 0;
  618. fail:
  619. if (req_buf) binrpc_free(req_buf);
  620. return res;
  621. fail2:
  622. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  623. "send_command: error when preparing params: %s", binrpc_error(ret));
  624. goto fail;
  625. }
  626. void binrpc_release_response(struct binrpc_response_handle *resp_handle) {
  627. if (resp_handle->reply_buf) {
  628. binrpc_free(resp_handle->reply_buf);
  629. resp_handle->reply_buf = NULL;
  630. }
  631. }
  632. int binrpc_get_response_type(struct binrpc_response_handle *resp_handle)
  633. {
  634. switch(resp_handle->in_pkt.type) {
  635. case BINRPC_FAULT:
  636. return 1;
  637. break;
  638. case BINRPC_REPL:
  639. return 0;
  640. break;
  641. default:
  642. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  643. "BUG: get_response_type: not a reply");
  644. return FATAL_ERROR;
  645. }
  646. }
  647. /* parses strings like "bla bla %v 10%% %v\n test=%v",
  648. * and stops at each %v, returning a pointer after the %v, setting *size
  649. * to the string length (not including %v) and *type to the corresponding
  650. * BINRPC type (for now only BINRPC_T_ALL).
  651. * To escape a '%', use "%%", and check for type==-1 (which means skip an call
  652. * again parse_fmt).
  653. * Usage:
  654. * n="test: %v,%v,%v\n";
  655. * while(*n){
  656. * s=n;
  657. * n=parse_fmt(n, &type, &size);
  658. * printf("%.*s", size, s);
  659. * if (type==-1)
  660. * continue;
  661. * else
  662. * printf("now we should get & print an object of type %d\n", type)
  663. * }
  664. */
  665. static char* parse_fmt(char* fmt, int* type, int* size)
  666. {
  667. char* s;
  668. s=fmt;
  669. do{
  670. for(;*fmt && *fmt!='%'; fmt++);
  671. if (*fmt=='%'){
  672. switch(*(fmt+1)){
  673. case 'v':
  674. *type=BINRPC_T_ALL;
  675. *size=(int)(fmt-s);
  676. return (fmt+2);
  677. break;
  678. case '%':
  679. /* escaped % */
  680. *size=(int)(fmt-s)+1;
  681. *type=-1; /* skip */
  682. return (fmt+2);
  683. break;
  684. }
  685. }
  686. }while(*fmt);
  687. *type=-1; /* no value */
  688. *size=(fmt-s);
  689. return fmt;
  690. }
  691. static void print_binrpc_val(struct binrpc_val* v, int ident)
  692. {
  693. int r;
  694. if ((v->type==BINRPC_T_STRUCT) && !v->u.end)
  695. ident--; /* fix to have strut beg. idented differently */
  696. for (r=0; r<ident; r++) putchar(' ');
  697. if (v->name.s){
  698. printf("%.*s: ", v->name.len, v->name.s);
  699. }
  700. switch(v->type){
  701. case BINRPC_T_INT:
  702. printf("%d", v->u.intval);
  703. break;
  704. case BINRPC_T_STR:
  705. case BINRPC_T_BYTES:
  706. printf("%.*s", v->u.strval.len, v->u.strval.s);
  707. break;
  708. case BINRPC_T_ARRAY:
  709. printf("%c", (v->u.end)?']':'[');
  710. break;
  711. case BINRPC_T_STRUCT:
  712. printf("%c", (v->u.end)?'}':'{');
  713. break;
  714. default:
  715. printf("ERROR: unknown type %d\n", v->type);
  716. }
  717. }
  718. int binrpc_print_response(struct binrpc_response_handle *resp_handle, char* fmt)
  719. {
  720. unsigned char* p;
  721. unsigned char* end;
  722. struct binrpc_val val;
  723. int ret;
  724. int rec;
  725. char *f;
  726. char* s;
  727. int f_size;
  728. int fmt_has_values;
  729. if (!resp_handle) {
  730. goto error;
  731. }
  732. resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0;
  733. p=resp_handle->reply_buf;
  734. end=p+resp_handle->in_pkt.tlen;
  735. rec=0;
  736. f=fmt;
  737. fmt_has_values=0;
  738. /* read body */
  739. while(p<end){
  740. if (f){
  741. do{
  742. if (*f==0)
  743. f=fmt; /* reset */
  744. s=f;
  745. f=parse_fmt(f, &val.type, &f_size);
  746. printf("%.*s", f_size, s);
  747. if (val.type!=-1){
  748. fmt_has_values=1;
  749. goto read_value;
  750. }
  751. }while(*f || fmt_has_values);
  752. val.type=BINRPC_T_ALL;
  753. }else{
  754. val.type=BINRPC_T_ALL;
  755. }
  756. read_value:
  757. val.name.s=0;
  758. val.name.len=0;
  759. p=binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret);
  760. if (ret<0){
  761. if (fmt)
  762. putchar('\n');
  763. /*if (ret==E_BINRPC_MORE_DATA)
  764. goto error_read_again;*/
  765. if (ret==E_BINRPC_EOP){
  766. printf("end of message detected\n");
  767. break;
  768. }
  769. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  770. "error while parsing the record %d,"
  771. " @%d: %02x : %s", rec,
  772. resp_handle->in_pkt.offset, *p, binrpc_error(ret));
  773. goto error;
  774. }
  775. rec++;
  776. if (fmt){
  777. print_binrpc_val(&val, 0);
  778. }else{
  779. print_binrpc_val(&val, resp_handle->in_pkt.in_struct+resp_handle->in_pkt.in_array);
  780. putchar('\n');
  781. }
  782. }
  783. if (fmt && *f){
  784. /* print the rest, with empty values */
  785. while(*f){
  786. s=f;
  787. f=parse_fmt(f, &val.type, &f_size);
  788. printf("%.*s", f_size, s);
  789. }
  790. }
  791. return 0;
  792. error:
  793. return FATAL_ERROR;
  794. /*error_read_again:
  795. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  796. "ERROR: more data needed");
  797. return -2;
  798. */
  799. }
  800. void binrpc_free_rpc_array(struct binrpc_val* a, int size)
  801. {
  802. int r;
  803. for (r=0; r<size; r++){
  804. if (a[r].name.s)
  805. binrpc_free(a[r].name.s);
  806. if ((a[r].type==BINRPC_T_STR || a[r].type==BINRPC_T_BYTES) &&
  807. a[r].u.strval.s){
  808. binrpc_free(a[r].u.strval.s);
  809. }
  810. }
  811. binrpc_free(a);
  812. }
  813. #define VAL_ARRAY_CHUNK 100
  814. int binrpc_parse_response(struct binrpc_val** vals, int* val_count,
  815. struct binrpc_response_handle *resp_handle)
  816. {
  817. struct binrpc_val val;
  818. unsigned char *p, *end;
  819. int ret, i;
  820. resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0;
  821. i=0;
  822. if (*val_count==0){
  823. *val_count=VAL_ARRAY_CHUNK; /* start with a reasonable size */
  824. }
  825. *vals = (struct binrpc_val*) binrpc_malloc(*val_count*sizeof(**vals));
  826. if (*vals == 0)
  827. goto error_mem;
  828. p = resp_handle->reply_buf;
  829. end = p + resp_handle->in_pkt.tlen;
  830. /* read body */
  831. while(p < end){
  832. val.type = BINRPC_T_ALL;
  833. val.name.s = 0;
  834. val.name.len = 0;
  835. p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret);
  836. if (ret<0){
  837. if (ret==E_BINRPC_EOP){
  838. break;
  839. }
  840. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  841. "ERROR while parsing the record %d,"
  842. " @%d: %02x : %s", i,
  843. resp_handle->in_pkt.offset, *p, binrpc_error(ret));
  844. goto error;
  845. }
  846. if (i >= *val_count){
  847. struct binrpc_val *t;
  848. t= (struct binrpc_val*) binrpc_realloc(*vals, (VAL_ARRAY_CHUNK+(*val_count))*sizeof(**vals));
  849. if (t==0)
  850. goto error_mem;
  851. *vals = t;
  852. *val_count += VAL_ARRAY_CHUNK;
  853. }
  854. (*vals)[i] = val;
  855. if (val.name.s){
  856. if (((*vals)[i].name.s=binrpc_malloc(val.name.len+1))==0)
  857. goto error_mem;
  858. memcpy((*vals)[i].name.s, val.name.s, val.name.len);
  859. (*vals)[i].name.s[val.name.len]=0; /* 0-term */
  860. }
  861. if (val.u.strval.s){
  862. if (val.type==BINRPC_T_STR){
  863. if (((*vals)[i].u.strval.s=
  864. binrpc_malloc(val.u.strval.len+1))==0)
  865. goto error_mem;
  866. memcpy((*vals)[i].u.strval.s, val.u.strval.s,
  867. val.u.strval.len);
  868. (*vals)[i].u.strval.s[val.u.strval.len]=0; /* 0-term */
  869. }else if (val.type==BINRPC_T_BYTES){
  870. if (((*vals)[i].u.strval.s=binrpc_malloc(val.u.strval.len))==0)
  871. goto error_mem;
  872. memcpy((*vals)[i].u.strval.s, val.u.strval.s,
  873. val.u.strval.len);
  874. }
  875. }
  876. i++;
  877. }
  878. if (i == 0) {
  879. binrpc_free(*vals);
  880. *vals = NULL;
  881. }
  882. else if (i<*val_count){
  883. /* do not try to save memory because it causes fragmentation when used ser mem utils and "regualar" memory leak
  884. struct binrpc_val *t;
  885. t = (struct binrpc_val*) binrpc_realloc(*vals, i*sizeof(**vals));
  886. if (t) *vals = t;
  887. */
  888. }
  889. *val_count = i;
  890. return 0;
  891. error_mem:
  892. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  893. "parse_response: out of memory");
  894. error:
  895. if (*vals){
  896. binrpc_free_rpc_array(*vals, i);
  897. *vals = NULL;
  898. }
  899. *val_count=0;
  900. return FATAL_ERROR;
  901. }
  902. int binrpc_parse_error_response(
  903. struct binrpc_response_handle *resp_handle,
  904. int *err_no,
  905. char **err)
  906. {
  907. struct binrpc_val val;
  908. unsigned char *p, *end;
  909. int ret;
  910. resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0;
  911. p = resp_handle->reply_buf;
  912. end = p+resp_handle->in_pkt.tlen;
  913. val.type=BINRPC_T_INT;
  914. val.name.s=0;
  915. val.name.len=0;
  916. p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret);
  917. if (ret < 0) {
  918. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  919. "parse_error_response: error when parsing reply (code): %s", binrpc_error(ret)
  920. );
  921. return FATAL_ERROR;
  922. }
  923. *err_no = val.u.intval;
  924. val.type=BINRPC_T_STR;
  925. p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret);
  926. if (ret < 0) {
  927. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  928. "parse_error_response: error when parsing reply (str): %s", binrpc_error(ret)
  929. );
  930. return FATAL_ERROR;
  931. }
  932. *err = val.u.strval.s; /* it's null terminated */
  933. return 0;
  934. }
  935. /* returns a pointer to a static buffer containing l in asciiz & sets len */
  936. static inline char* int2str_internal(unsigned int l, int* len)
  937. {
  938. static char r[INT2STR_MAX_LEN];
  939. int i;
  940. i=INT2STR_MAX_LEN-2;
  941. r[INT2STR_MAX_LEN-1]=0; /* null terminate */
  942. do{
  943. r[i]=l%10+'0';
  944. i--;
  945. l/=10;
  946. }while(l && (i>=0));
  947. if (l && (i<0)){
  948. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  949. "BUG: int2str_internal: overflow");
  950. }
  951. if (len) *len=(INT2STR_MAX_LEN-2)-i;
  952. return &r[i+1];
  953. }
  954. static int realloc_buf(unsigned char** buf, int* buf_len, int req_len)
  955. {
  956. unsigned char* tmp_buf;
  957. int orig_len;
  958. orig_len = (*buf == NULL) ? 0 : strlen((char *) *buf);
  959. *buf_len += (TEXT_BUFF_ALLOC_CHUNK < req_len) ? TEXT_BUFF_ALLOC_CHUNK + req_len : TEXT_BUFF_ALLOC_CHUNK;
  960. if (*buf == NULL)
  961. tmp_buf = (unsigned char *) binrpc_malloc(orig_len + *buf_len);
  962. else
  963. tmp_buf = (unsigned char *) binrpc_realloc(*buf, orig_len + *buf_len);
  964. if (tmp_buf == 0) {
  965. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  966. "ERROR: out of memory");
  967. return FATAL_ERROR;
  968. }
  969. *buf = tmp_buf;
  970. (*buf)[orig_len] = '\0';
  971. return 0;
  972. }
  973. static inline int str2buffer(unsigned char** buf, int* buf_len, int* pos,
  974. char* data, int data_len)
  975. {
  976. if (*buf_len < data_len) {
  977. if(realloc_buf(buf, buf_len, data_len) != 0) {
  978. return FATAL_ERROR;
  979. }
  980. }
  981. memcpy(&(*buf)[*pos], data, data_len);
  982. *pos += data_len;
  983. *buf_len -= data_len;
  984. return 0;
  985. }
  986. static inline int char2buffer(unsigned char** buf, int* buf_len, int* pos,
  987. char data)
  988. {
  989. if (*buf_len < 1) {
  990. if(realloc_buf(buf, buf_len, 1) != 0) {
  991. return FATAL_ERROR;
  992. }
  993. }
  994. (*buf)[*pos] = data;
  995. ++(*pos);
  996. --(*buf_len);
  997. return 0;
  998. }
  999. static int val2buffer(struct binrpc_val* v, unsigned char** buf,
  1000. int *buf_len, int* pos)
  1001. {
  1002. char *number;
  1003. int num_len;
  1004. if (v->name.s){
  1005. if(str2buffer(buf, buf_len, pos, v->name.s, v->name.len) != 0) {
  1006. return FATAL_ERROR;
  1007. }
  1008. if(str2buffer(buf, buf_len, pos, ": ", strlen(": ")) != 0) { /* TODO: common format */
  1009. return FATAL_ERROR;
  1010. }
  1011. }
  1012. switch(v->type){
  1013. case BINRPC_T_INT:
  1014. num_len = 0;
  1015. number = NULL;
  1016. number = int2str_internal(v->u.intval, &num_len);
  1017. if (number == NULL) {
  1018. printf("ERROR: Conversion of %d into string failed.\n", v->type);
  1019. return FATAL_ERROR;
  1020. }
  1021. if(str2buffer(buf, buf_len, pos, number, num_len) != 0) {
  1022. return FATAL_ERROR;
  1023. }
  1024. break;
  1025. case BINRPC_T_STR:
  1026. case BINRPC_T_BYTES:
  1027. if(str2buffer(buf, buf_len, pos, v->u.strval.s, v->u.strval.len) != 0) {
  1028. return FATAL_ERROR;
  1029. }
  1030. break;
  1031. case BINRPC_T_ARRAY:
  1032. if(char2buffer(buf, buf_len, pos, (v->u.end) ? ']' : '[') != 0) {
  1033. return FATAL_ERROR;
  1034. }
  1035. break;
  1036. case BINRPC_T_STRUCT:
  1037. if(char2buffer(buf, buf_len, pos, (v->u.end) ? '}' : '{') != 0) {
  1038. return FATAL_ERROR;
  1039. }
  1040. break;
  1041. default:
  1042. printf("ERROR: unknown type %d\n", v->type);
  1043. return FATAL_ERROR;
  1044. };
  1045. return 0;
  1046. }
  1047. int binrpc_response_to_text(
  1048. struct binrpc_response_handle *resp_handle,
  1049. unsigned char** txt_rsp, int* txt_rsp_len, char delimiter)
  1050. {
  1051. unsigned char* p;
  1052. unsigned char* end;
  1053. struct binrpc_val val;
  1054. int ret;
  1055. int rec;
  1056. int pos;
  1057. pos = 0;
  1058. if (!resp_handle) {
  1059. goto error;
  1060. }
  1061. resp_handle->in_pkt.offset = resp_handle->in_pkt.in_struct = resp_handle->in_pkt.in_array = 0;
  1062. p=resp_handle->reply_buf;
  1063. end=p+resp_handle->in_pkt.tlen;
  1064. rec=0;
  1065. if (*txt_rsp == NULL) {
  1066. *txt_rsp_len = 0;
  1067. if (realloc_buf(txt_rsp, txt_rsp_len, 0) != 0) {
  1068. goto error;
  1069. }
  1070. }
  1071. /* read body */
  1072. while(p<end){
  1073. val.type=BINRPC_T_ALL;
  1074. val.name.s=0;
  1075. val.name.len=0;
  1076. p = binrpc_read_record(&resp_handle->in_pkt, p, end, &val, &ret);
  1077. if (ret < 0) {
  1078. if (ret == E_BINRPC_EOP) {
  1079. printf("end of message detected\n");
  1080. break;
  1081. }
  1082. snprintf(binrpc_last_errs, sizeof(binrpc_last_errs)-1,
  1083. "ERROR while parsing the record %d,"
  1084. " @%d: %02x : %s", rec, resp_handle->in_pkt.offset, *p, binrpc_error(ret));
  1085. goto error;
  1086. }
  1087. rec++;
  1088. if (val2buffer(&val, txt_rsp, txt_rsp_len, &pos) != 0) {
  1089. goto error;
  1090. }
  1091. if(char2buffer(txt_rsp, txt_rsp_len, &pos, delimiter) != 0) {
  1092. goto error;
  1093. }
  1094. }
  1095. /* rewrite last char - we don't need delimiter there */
  1096. (*txt_rsp)[pos-1] = '\0';
  1097. /*
  1098. if(char2buffer(txt_rsp, txt_rsp_len, &pos, '\0') != 0) {
  1099. goto error;
  1100. }
  1101. */
  1102. return 0;
  1103. error:
  1104. return FATAL_ERROR;
  1105. }
  1106. int main(int argc, char** argv)
  1107. {
  1108. struct binrpc_response_handle resp_handle;
  1109. unsigned char* txt_rsp = NULL;
  1110. int txt_rsp_len = 0;
  1111. struct binrpc_handle handle;
  1112. struct binrpc_val *vals = NULL;
  1113. int cnt, i, err_no;
  1114. char *errs;
  1115. if (argc < 2) goto err;
  1116. if (binrpc_open_connection_url(&handle, argv[1]) < 0) goto err2;
  1117. if (binrpc_send_command(&handle, argv[2], argv+3, argc-3, &resp_handle) < 0) {
  1118. binrpc_close_connection(&handle);
  1119. goto err2;
  1120. }
  1121. binrpc_close_connection(&handle);
  1122. if (binrpc_response_to_text(&resp_handle, &txt_rsp, &txt_rsp_len, '\n') < 0) goto err3;
  1123. fprintf(stdout, "binrpc_response_to_text():\n--------------------------\n%s\n", txt_rsp);
  1124. fprintf(stdout, "\nbinrpc_print_response():\n------------------------\n");
  1125. binrpc_print_response(&resp_handle, NULL);
  1126. fprintf(stdout, "\nbinrpc_parse_response():\n------------------------\n");
  1127. cnt = 0;
  1128. switch (binrpc_get_response_type(&resp_handle)) {
  1129. case 0:
  1130. if (binrpc_parse_response(&vals, &cnt, &resp_handle) < 0) goto err3;
  1131. fprintf(stdout, "#Records: %d\n", cnt);
  1132. for (i = 0; i < cnt; i++) {
  1133. fprintf(stdout, "#%.2d: type:%d name:%.*s\n", i, vals[i].type, vals[i].name.len, vals[i].name.s);
  1134. }
  1135. break;
  1136. case 1:
  1137. if (binrpc_parse_error_response(&resp_handle, &err_no, &errs) <0) goto err3;
  1138. fprintf(stdout, "%d %s\n", err_no, errs);
  1139. break;
  1140. default:
  1141. fprintf(stdout, "Unknown response type: %d\n", binrpc_get_response_type(&resp_handle));
  1142. break;
  1143. }
  1144. if (vals != NULL) {
  1145. binrpc_free_rpc_array(vals, cnt);
  1146. }
  1147. if (txt_rsp != NULL) {
  1148. binrpc_free(txt_rsp);
  1149. }
  1150. binrpc_release_response(&resp_handle);
  1151. return 0;
  1152. err:
  1153. fprintf(stderr, "Usage: %s url mathod [params]\n", NAME);
  1154. return -1;
  1155. err3:
  1156. if (vals != NULL) {
  1157. binrpc_free_rpc_array(vals, cnt);
  1158. }
  1159. if (txt_rsp) {
  1160. binrpc_free(txt_rsp);
  1161. }
  1162. binrpc_release_response(&resp_handle);
  1163. err2:
  1164. fprintf(stderr, "ERROR: %s\n", binrpc_get_last_errs());
  1165. return -2;
  1166. }