1 /*****************************************************************************
2 *
3 * FILE: sxmlrpc.c
4 * DESCRIPTION: Skimpy XML-RPC library file
5 * DATE: Sat, Mar 18 2006
6 * UPDATED: Mon, Jan 26 2009
7 * AUTHOR: Kouichi ABE (WALL) / ��������
8 * E-MAIL: kouichi@MysticWALL.COM
9 * URL: http://www.MysticWALL.COM/
10 * COPYRIGHT: (c) 2006-2009 �������졿Kouichi ABE (WALL), All rights reserved.
11 * LICENSE:
12 *
13 * Copyright (c) 2006-2009 Kouichi ABE (WALL) <kouichi@MysticWALL.COM>,
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 *
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * $Id: sxmlrpc.c,v 1.11 2010/03/26 07:56:17 kouichi Exp $
39 *
40 *****************************************************************************/
41
42 #if HAVE_CONFIG_H
43 #include "config.h"
44 #endif /* HAVE_CONFIG_H */
45
46 #include <stdio.h>
47 #if HAVE_STDLIB_H
48 #include <stdlib.h>
49 #endif /* HAVE_STDLIB_H */
50 #if HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif /* HAVE_UNISTD_H */
53 #if HAVE_STRING_H
54 #include <string.h>
55 #endif /* HAVE_STRING_H */
56 #if HAVE_FCNTL_H
57 #include <fcntl.h>
58 #endif /* HAVE_FCNTL_H */
59 #if HAVE_NETINET_IN_H
60 #include <netinet/in.h>
61 #endif /* HAVE_NETINET_IN_H */
62 #if HAVE_SYS_TYPES_H
63 #include <sys/types.h>
64 #endif /* HAVE_SYS_TYPES_H */
65 #if HAVE_SYS_STAT_H
66 #include <sys/stat.h>
67 #endif /* HAVE_SYS_STAT_H */
68 #include <sys/mman.h>
69 #if HAVE_SYS_SOCKET_H
70 #include <sys/socket.h>
71 #endif /* HAVE_SYS_SOCKET_H */
72 #if HAVE_NETDB_H
73 #include <netdb.h>
74 #endif /* HAVE_NETDB_H */
75 #if HAVE_NETINET_IN_H
76 #include <netinet/in.h>
77 #endif /* HAVE_NETINET_IN_H */
78 #include <arpa/inet.h>
79 #if TIME_WITH_SYS_TIME
80 # include <sys/time.h>
81 # include <time.h>
82 #else
83 # if HAVE_SYS_TIME_H
84 # include <sys/time.h>
85 # else
86 # include <time.h>
87 # endif /* HAVE_SYS_TIME_H */
88 #endif /* TIME_WITH_SYS_TIME */
89 #include <signal.h>
90 #include <errno.h>
91 #include "sxml.h"
92 #include "sxmlrpc.h"
93
94 /******************************************************************************
95 *
96 * Macros and structures definition
97 *
98 *****************************************************************************/
99 #define EOL '\0'
100 #define LF '\012'
101 #define CR '\015'
102 #define SPC '\040'
103 #define CRLF "\015\012"
104
105 /* easy network I/O manager */
106 typedef struct _netfd {
107 #define netfd_fileno(x) ((x)->osfd)
108 int osfd; /* underlying OS file descriptor */
109 #define NETFD_BUFSIZE (1024*4)
110 struct { /* read buffer */
111 int total; /* initialize to 0 */
112 char * bufp; /* initialize to buf */
113 char buf[NETFD_BUFSIZE];
114 } rb;
115 } netfd_t;
116 #define NETFD_SEEK_SET SEEK_SET
117 #define NETFD_SEEK_CUR SEEK_CUR
118 #define NETFD_SEEK_END SEEK_END
119
120 #define NETFD_DEF_BACKLOG (8)
121
122 /* default encoding */
123 #if 1
124 #define SXMLRPC_ENCODING "us-ascii"
125 #else
126 #define SXMLRPC_ENCODING "utf-8"
127 #endif
128
129 /* default XML-RPC XML version */
130 #define SXMLRPC_XML_VERSION "1.0"
131
132 /* default User-Agent of Request Header */
133 #define SXMLRPC_USER_AGENT SXMLRPC_VERSION
134
135 /* default Server of Response Header */
136 #define SXMLRPC_SERVER SXMLRPC_VERSION
137
138 /* default Content-Type of Request Header */
139 #define SXMLRPC_CONTENT_TYPE "text/xml"
140
141 /* headers */
142 #define CONTENT_LENGTH "Content-Length"
143 #define CONTENT_TYPE "Content-Type"
144
145 /* mkstemp(3) */
146 #define SXMLRPC_TEMPLATE "/tmp/.sxmlrpc.XXXXXX"
147
148 #define xfree(x) \
149 do { if ((x)!=NULL) { free((x)); (x)=NULL; } } while (0)
150
151 /******************************************************************************
152 *
153 * Lobal functions declaration
154 *
155 *****************************************************************************/
156 static void flush_params(sxmlrpc_params_t *);
157 static int make_request_body(sxmlrpc_t *, const char *,
158 sxmlrpc_param_t *, size_t);
159 static sxml_node_t * graft_request_body(const char *, sxmlrpc_param_t *,
160 size_t);
161 static int make_request_head(sxmlrpc_t *);
162 static int make_response_body(sxmlrpc_t *, sxmlrpc_param_t *);
163 static sxml_node_t * graft_response_body(sxmlrpc_param_t *);
164 static sxml_node_t * graft_fault_body(sxmlrpc_param_t *);
165 static int make_response_head(sxmlrpc_t *);
166 static int send_message(sxmlrpc_t *, netfd_t *, netfd_t *);
167 static sxml_node_t * recv_message(sxmlrpc_t *, netfd_t *, netfd_t *);
168 static int parse_start_line(sxmlrpc_t *, char *);
169 static int make_new_value(sxml_node_t *, sxmlrpc_value_t *);
170 static int get_call_params(sxmlrpc_t *, sxml_node_t *);
171 static size_t set_call_params(sxmlrpc_t *, sxml_node_t *);
172 static sxml_node_t * get_response_value(sxmlrpc_t *, sxml_node_t *);
173 static int set_value(sxmlrpc_value_t *, sxml_node_t *);
174 static int set_value_member(sxmlrpc_member_t *, sxml_node_t *);
175 static int set_value_array(sxmlrpc_value_t *, sxml_node_t *);
176 static size_t count_children(sxml_node_t *);
177
178 static netfd_t * netfd_open(const char *, int, mode_t);
179 static netfd_t * netfd_fdopen(int);
180 static netfd_t * netfd_new(int);
181 static int netfd_close(netfd_t *);
182 static off_t netfd_seek(netfd_t *, off_t, int);
183 static ssize_t netfd_read(netfd_t *, void *, size_t);
184 static ssize_t netfd_write(netfd_t *, const void *, size_t);
185 static ssize_t netfd_readline(netfd_t *, void *, size_t);
186 static ssize_t one_read(netfd_t *, char *);
187 static int netfd_readbuf(netfd_t *);
188 static netfd_t * netfd_mkstemp(char *);
189 #if HAVE_FREEBSD_SENDFILE
190 static int netfd_sendfile(netfd_t *, netfd_t *, off_t, size_t,
191 struct sf_hdtr *, off_t *, int);
192 #elif HAVE_LINUX_SENDFILE
193 static int netfd_sendfile(netfd_t *, netfd_t *, off_t, size_t,
194 void *, off_t *, int);
195 #else
196 static int netfd_sendfile(netfd_t *, netfd_t *, off_t, size_t,
197 void *, off_t *, int);
198 #endif
199 static void sigalrm(int signo);
200 static netfd_t * netfd_tcp_client(const char *, const char *);
201 static netfd_t * netfd_tcp_server(const char *, const char *, const int);
202 static netfd_t * netfd_accept(netfd_t *, struct sockaddr *, socklen_t *);
203 static int netfd_sock_ntop(const struct sockaddr * sa0,
204 char ** ipaddr);
205 static int my_close(int fd);
206
207 /******************************************************************************
208 *
209 * Lobal variable definition
210 *
211 *****************************************************************************/
212 static sig_atomic_t timedout = 0; /* flag for connect() */
213
214 /******************************************************************************
215 *
216 * Functions definition
217 *
218 *****************************************************************************/
219 sxmlrpc_t *
sxmlrpc_new(hostname,servname,path)220 sxmlrpc_new(hostname, servname, path)
221 const char * hostname;
222 const char * servname;
223 const char * path;
224 {
225 sxmlrpc_t * new;
226
227 new = (sxmlrpc_t *)calloc(1, sizeof(sxmlrpc_t));
228 if (new != NULL) {
229 new->hostname = strdup(hostname);
230 new->servname = strdup(servname);
231 new->path = strdup(path);
232 new->encoding = NULL;
233 }
234
235 return new;
236 }
237
238 void
sxmlrpc_free(sxRPC)239 sxmlrpc_free(sxRPC)
240 sxmlrpc_t * sxRPC;
241 {
242 if (sxRPC != NULL) {
243 xfree(sxRPC->hostname);
244 xfree(sxRPC->servname);
245 xfree(sxRPC->path);
246 xfree(sxRPC->encoding);
247 xfree(sxRPC);
248 }
249 }
250
251 void
sxmlrpc_flush(sxRPC)252 sxmlrpc_flush(sxRPC)
253 sxmlrpc_t * sxRPC;
254 {
255 if (sxRPC != NULL) {
256 switch (sxRPC->role) {
257 case SXMLRPC_ROLE_SERVER:
258 xfree(sxRPC->call_method);
259 flush_params(&sxRPC->call_params);
260 break;
261 case SXMLRPC_ROLE_CLIENT:
262 sxmlrpc_flush_value(&sxRPC->response_value);
263 default:
264 break;
265 }
266 }
267 }
268
269 void
sxmlrpc_flush_value(v)270 sxmlrpc_flush_value(v)
271 sxmlrpc_value_t * v;
272 {
273 if (v != NULL) {
274 register size_t i;
275
276 switch (v->type) {
277 case SXMLRPC_VALUE_STRING:
278 case SXMLRPC_VALUE_DATETIME:
279 case SXMLRPC_VALUE_BASE64:
280 xfree(v->u.sval);
281 break;
282 case SXMLRPC_VALUE_STRUCT:
283 for (i = 0; i < v->u.tval.size; i++) {
284 xfree(v->u.tval.member[i].name);
285 sxmlrpc_flush_value(&v->u.tval.member[i].value);
286 }
287 xfree(v->u.tval.member);
288 v->u.tval.size = 0;
289 break;
290 case SXMLRPC_VALUE_ARRAY:
291 for (i = 0; i < v->u.aval.size; i++) {
292 sxmlrpc_flush_value(&v->u.aval.value[i]);
293 }
294 xfree(v->u.aval.value);
295 v->u.aval.size = 0;
296 break;
297 default:
298 break;
299 }
300 }
301 }
302
303 static void
flush_params(params)304 flush_params(params)
305 sxmlrpc_params_t * params;
306 {
307 if (params->param != NULL) {
308 register size_t i;
309
310 for (i = 0; i < params->size; i++) {
311 sxmlrpc_flush_value(¶ms->param[i].value);
312 }
313 xfree(params->param);
314 params->size = 0;
315 }
316 }
317
318 /*****************************************************************************/
319
320 int
sxmlrpc_call(sxRPC,method_name,param,param_num)321 sxmlrpc_call(sxRPC, method_name, param, param_num)
322 sxmlrpc_t * sxRPC;
323 const char * method_name;
324 sxmlrpc_param_t * param;
325 size_t param_num;
326 {
327 netfd_t * nfd;
328 char template[] = SXMLRPC_TEMPLATE;
329 int status = -1;
330
331 if (sxRPC == NULL) {
332 errno = EINVAL;
333 return -1;
334 }
335
336 nfd = netfd_mkstemp(template);
337 if (nfd != NULL) {
338 sxRPC->msgbdy_fd = netfd_fileno(nfd);
339 sxRPC->role = SXMLRPC_ROLE_CLIENT;
340 sxRPC->method = SXMLRPC_METHOD_CALL;
341 if (make_request_body(sxRPC, method_name, param, param_num) == 0) {
342 if (make_request_head(sxRPC) == 0) {
343 netfd_t * nsd;
344
345 nsd = netfd_tcp_client(sxRPC->hostname, sxRPC->servname);
346 if (nsd != NULL) {
347 status = send_message(sxRPC, nfd, nsd);
348 if (status == 0) {
349 netfd_close(nfd);
350 nfd = netfd_open(template, O_RDWR|O_TRUNC, 0600);
351 if (nfd != NULL) {
352 sxml_node_t * root;
353
354 root = recv_message(sxRPC, nfd, nsd);
355 if (root != NULL) {
356 sxml_node_t * np;
357
358 np = get_response_value(sxRPC, root);
359 if (np != NULL) {
360 status = set_value(&sxRPC->response_value, np);
361 }
362 sxml_delete_node(root);
363 }
364 }
365 }
366 netfd_close(nsd);
367 }
368 }
369 }
370 unlink(template);
371 netfd_close(nfd);
372 }
373
374 return status;
375 }
376
377 static int
make_request_body(sxRPC,method_name,param,param_num)378 make_request_body(sxRPC, method_name, param, param_num)
379 sxmlrpc_t * sxRPC;
380 const char * method_name;
381 sxmlrpc_param_t * param;
382 size_t param_num;
383 {
384 int fd;
385 int status = -1;
386
387 fd = dup(sxRPC->msgbdy_fd);
388 if (fd != -1) {
389 register FILE * fout;
390
391 fout = fdopen(fd, "r+");
392 if (fout != NULL) {
393 sxml_node_t * root;
394
395 root = graft_request_body(method_name, param, param_num);
396 if (root != NULL) {
397 sxml_node_t * np;
398
399 np = sxml_new_prolog(root, "xml");
400 if (np != NULL) {
401 sxml_set_attribute(np, "encoding",
402 sxRPC->encoding ? sxRPC->encoding
403 : SXMLRPC_ENCODING);
404 sxml_set_attribute(np, "version", SXMLRPC_XML_VERSION);
405 }
406 sxml_print_tree(root, fout);
407 sxml_delete_node(root);
408 if (fseek(fout, 0L, SEEK_SET) == 0) {
409 struct stat sbuf;
410
411 status = fstat(fd, &sbuf);
412 if (status == 0) {
413 sxRPC->msgbdy_size = (size_t)sbuf.st_size;
414 }
415 }
416 }
417 fclose(fout);
418 }
419 close(fd);
420 }
421
422 return status;
423 }
424
425 static sxml_node_t *
graft_request_body(method_name,param,param_num)426 graft_request_body(method_name, param, param_num)
427 const char * method_name;
428 sxmlrpc_param_t * param;
429 size_t param_num;
430 {
431 sxml_node_t * root;
432
433 root = sxml_new_vertex();
434 if (root != NULL) {
435 sxml_node_t * mc;
436
437 mc = sxml_new_element(root, "methodCall");
438 if (mc != NULL) {
439 sxml_node_t * ps;
440
441 sxml_set_node(mc, "methodName", method_name);
442 ps = sxml_new_element(mc, "params");
443 if (ps != NULL) {
444 register size_t i;
445
446 for (i = 0; i < param_num; i++) {
447 sxml_node_t * p;
448
449 p = sxml_new_element(ps, "param");
450 if (p != NULL) {
451 make_new_value(p, ¶m[i].value);
452 }
453 }
454 }
455 }
456 }
457
458 return root;
459 }
460
461 static int
make_request_head(sxRPC)462 make_request_head(sxRPC)
463 sxmlrpc_t * sxRPC;
464 {
465 sxRPC->msghdr_size = asprintf(&sxRPC->msghdr_text,
466 "POST %s HTTP/1.0" CRLF
467 "Host: %s:%s" CRLF
468 "User-Agent: " SXMLRPC_USER_AGENT CRLF
469 "Content-Type: " SXMLRPC_CONTENT_TYPE CRLF
470 "Content-Length: %d" CRLF
471 CRLF ,
472 sxRPC->path, sxRPC->hostname, sxRPC->servname,
473 sxRPC->msgbdy_size);
474 return (sxRPC->msghdr_text != NULL) ? 0 : -1;
475 }
476
477 /*****************************************************************************/
478
479 static sxmlrpc_boolean_t forever = true;
480
trap(int signo)481 static void trap(int signo) { forever = false; }
482
483 int
sxmlrpc_server(sxRPC,backlog,callback)484 sxmlrpc_server(sxRPC, backlog, callback)
485 sxmlrpc_t * sxRPC;
486 const int backlog;
487 sxmlrpc_callback_t callback;
488 {
489 netfd_t * listenfd;
490
491 if (callback == NULL) {
492 errno = EINVAL;
493 return -1;
494 }
495
496 listenfd = netfd_tcp_server(sxRPC->hostname, sxRPC->servname, backlog);
497 if (listenfd != NULL) {
498 struct sigaction act;
499
500 sigemptyset(&act.sa_mask);
501 act.sa_flags = 0;
502 act.sa_handler = (void *)trap;
503 sigaction(SIGINT, &act, NULL);
504 sigaction(SIGQUIT, &act, NULL);
505 sigaction(SIGTERM, &act, NULL);
506 sigaction(SIGBUS, &act, NULL);
507 sigaction(SIGSEGV, &act, NULL);
508
509 while (forever) {
510 netfd_t * connfd;
511 struct sockaddr addr;
512 socklen_t addrlen;
513
514 connfd = netfd_accept(listenfd, &addr, &addrlen);
515 if (connfd != NULL) {
516 netfd_t * nfd;
517 char template[] = SXMLRPC_TEMPLATE;
518
519 nfd = netfd_mkstemp(template);
520 if (nfd != NULL) {
521 sxml_node_t * root;
522
523 sxRPC->msgbdy_fd = netfd_fileno(nfd);
524
525 root = recv_message(sxRPC, nfd, connfd);
526 if (root != NULL) {
527 int status;
528
529 status = get_call_params(sxRPC, root);
530 if (status != -1) {
531 sxmlrpc_param_t param;
532 char * client;
533
534 status = netfd_sock_ntop(&addr, &client);
535 if ((*callback)(client, sxmlrpc_method_name(sxRPC),
536 &sxmlrpc_call_params(sxRPC), ¶m) == 0) {
537 sxmlrpc_response_ok(sxRPC);
538 }
539 else {
540 sxmlrpc_response_fault(sxRPC);
541 }
542 if (status == 0) { free(client); }
543
544 netfd_close(nfd);
545 nfd = netfd_open(template, O_RDWR|O_TRUNC, 0600);
546 if (nfd != NULL) {
547 if (make_response_body(sxRPC, ¶m) == 0) {
548 if (make_response_head(sxRPC) == 0) {
549 send_message(sxRPC, nfd, connfd);
550 }
551 }
552 }
553 sxmlrpc_flush(sxRPC);
554 sxmlrpc_flush_value(¶m.value);
555 }
556 sxml_delete_node(root);
557 }
558 unlink(template);
559 netfd_close(nfd);
560 }
561 netfd_close(connfd);
562 }
563 }
564 netfd_close(listenfd);
565 }
566
567 return 0;
568 }
569
570 static int
make_response_body(sxRPC,param)571 make_response_body(sxRPC, param)
572 sxmlrpc_t * sxRPC;
573 sxmlrpc_param_t * param;
574 {
575 int fd;
576 int status = -1;
577
578 fd = dup(sxRPC->msgbdy_fd);
579 if (fd != -1) {
580 register FILE * fout;
581
582 fout = fdopen(fd, "r+");
583 if (fout != NULL) {
584 sxml_node_t * root = NULL;
585
586 switch (sxRPC->method) {
587 case SXMLRPC_METHOD_RESPONSE:
588 root = graft_response_body(param);
589 break;
590 case SXMLRPC_METHOD_RESPONSE_FAULT:
591 root = graft_fault_body(param);
592 break;
593 default:
594 break;
595 }
596 if (root != NULL) {
597 sxml_node_t * np;
598
599 np = sxml_new_prolog(root, "xml");
600 if (np != NULL) {
601 sxml_set_attribute(np, "encoding",
602 sxRPC->encoding ? sxRPC->encoding
603 : SXMLRPC_ENCODING);
604 sxml_set_attribute(np, "version", SXMLRPC_XML_VERSION);
605 }
606 sxml_print_tree(root, fout);
607 sxml_delete_node(root);
608 if (fseek(fout, 0L, SEEK_SET) == 0) {
609 struct stat sbuf;
610
611 status = fstat(fd, &sbuf);
612 if (status == 0) {
613 sxRPC->msgbdy_size = (size_t)sbuf.st_size;
614 }
615 }
616 }
617 fclose(fout);
618 }
619 close(fd);
620 }
621
622 return status;
623 }
624
625 static sxml_node_t *
graft_response_body(param)626 graft_response_body(param)
627 sxmlrpc_param_t * param;
628 {
629 sxml_node_t * root;
630
631 root = sxml_new_vertex();
632 if (root != NULL) {
633 sxml_node_t * mr;
634
635 mr = sxml_new_element(root, "methodResponse");
636 if (mr != NULL) {
637 sxml_node_t * ps;
638
639 ps = sxml_new_element(mr, "params");
640 if (ps != NULL) {
641 sxml_node_t * p;
642
643 p = sxml_new_element(ps, "param");
644 if (p != NULL) {
645 make_new_value(p, ¶m->value);
646 }
647 }
648 }
649 }
650
651 return root;
652 }
653
654 static sxml_node_t *
graft_fault_body(param)655 graft_fault_body(param)
656 sxmlrpc_param_t * param;
657 {
658 sxml_node_t * root;
659
660 root = sxml_new_vertex();
661 if (root != NULL) {
662 sxml_node_t * mr;
663
664 mr = sxml_new_element(root, "methodResponse");
665 if (mr != NULL) {
666 sxml_node_t * fp;
667
668 fp = sxml_new_element(mr, "fault");
669 if (fp != NULL) {
670 make_new_value(fp, ¶m->value);
671 }
672 }
673 }
674
675 return root;
676 }
677
678 static int
make_response_head(sxRPC)679 make_response_head(sxRPC)
680 sxmlrpc_t * sxRPC;
681 {
682 sxRPC->msghdr_size = asprintf(&sxRPC->msghdr_text,
683 "HTTP/1.0 200 OK" CRLF
684 "Connection: close" CRLF
685 "Content-Type: " SXMLRPC_CONTENT_TYPE CRLF
686 "Content-Length: %d" CRLF
687 "Server: " SXMLRPC_SERVER CRLF
688 CRLF ,
689 sxRPC->msgbdy_size);
690 return (sxRPC->msghdr_text != NULL) ? 0 : -1;
691 }
692
693
694 /*****************************************************************************/
695
696 static int
send_message(sxRPC,nfd,nsd)697 send_message(sxRPC, nfd, nsd)
698 sxmlrpc_t * sxRPC;
699 netfd_t * nfd;
700 netfd_t * nsd;
701 {
702 int status = -1;
703 ssize_t n;
704
705 n = netfd_write(nsd, sxRPC->msghdr_text, (size_t)sxRPC->msghdr_size);
706 if (n == (ssize_t)sxRPC->msghdr_size) {
707 off_t sbytes;
708
709 status = netfd_sendfile(nfd, nsd, 0, sxRPC->msgbdy_size, NULL, &sbytes, 0);
710 }
711 xfree(sxRPC->msghdr_text);
712
713 return status;
714 }
715
716 static sxml_node_t *
recv_message(sxRPC,nfd,nsd)717 recv_message(sxRPC, nfd, nsd)
718 sxmlrpc_t * sxRPC;
719 netfd_t * nfd;
720 netfd_t * nsd;
721 {
722 char buf[BUFSIZ];
723 ssize_t n;
724
725 memset(buf, 0, sizeof(buf));
726 n = netfd_readline(nsd, buf, sizeof(buf));
727 if (n > 0) {
728 size_t len = 0; /* Content-Length */
729 size_t l;
730
731 if (parse_start_line(sxRPC, buf) == -1) {
732 return NULL;
733 }
734
735 do {
736 #define MAX_TOKEN (2)
737 char ** ap;
738 char * args[MAX_TOKEN];
739 char * p;
740
741 memset(buf, 0, sizeof(buf));
742 n = netfd_readline(nsd, buf, sizeof(buf));
743 if (n <= 0) {
744 return NULL;
745 }
746 for (n = 0, p = buf, ap = args; (*ap = strsep(&p, ": \r\n")) != NULL; ) {
747 if (**ap != EOL) {
748 n++;
749 if (++ap >= &args[MAX_TOKEN]) {
750 break;
751 }
752 }
753 }
754 if (n == MAX_TOKEN) {
755 if (strncmp(args[0], CONTENT_LENGTH, sizeof(CONTENT_LENGTH) - 1) == 0) {
756 len = (size_t)strtol(args[1], (char **)NULL, 10);
757 }
758 else if (strncmp(args[0], CONTENT_TYPE,
759 sizeof(CONTENT_TYPE) - 1) == 0) {
760 if (strncmp(args[1], SXMLRPC_CONTENT_TYPE,
761 sizeof(SXMLRPC_CONTENT_TYPE) - 1) != 0) {
762 return NULL;
763 }
764 }
765 }
766 } while (buf[0] != EOL);
767
768 for (n = 0, l = 0; l < len; l += n) {
769 memset(buf, 0, sizeof(buf));
770 n = netfd_read(nsd, buf, sizeof(buf));
771 if (n > 0) {
772 if (netfd_write(nfd, buf, (size_t)n) != n) {
773 return NULL;
774 }
775 }
776 else {
777 return NULL;
778 }
779 }
780 netfd_seek(nfd, 0L, NETFD_SEEK_SET);
781
782 return sxml_parse_file(nfd->osfd);
783 }
784
785 return NULL;
786 }
787
788 static int
parse_start_line(sxRPC,buf)789 parse_start_line(sxRPC, buf)
790 sxmlrpc_t * sxRPC;
791 char * buf;
792 {
793 #define MAX_START_LINE_TOKEN (3)
794 char ** ap;
795 char * args[MAX_START_LINE_TOKEN];
796 char * p;
797 int n;
798
799 for (n = 0, p = buf, ap = args; (*ap = strsep(&p, " \r\n")) != NULL; ) {
800 if (**ap != EOL) {
801 n++;
802 if (++ap >= &args[MAX_START_LINE_TOKEN]) {
803 break;
804 }
805 }
806 }
807 if (n == MAX_START_LINE_TOKEN) {
808 switch (sxRPC->role) {
809 case SXMLRPC_ROLE_SERVER:
810 return (strcmp(args[0], "POST") == 0) ? 0 : -1;
811 case SXMLRPC_ROLE_CLIENT:
812 return (strcmp(args[1], "200") == 0) ? 0 : -1;
813 default:
814 break;
815 }
816 }
817
818 return -1;
819 }
820
821 /*****************************************************************************/
822
823 static int
make_new_value(node,value)824 make_new_value(node, value)
825 sxml_node_t * node;
826 sxmlrpc_value_t * value;
827 {
828 sxml_node_t * ep;
829
830 ep = sxml_new_element(node, "value");
831 if (ep != NULL) {
832 sxml_node_t * np = NULL;
833 char * s;
834
835 switch (value->type) {
836 case SXMLRPC_VALUE_INTEGER:
837 asprintf(&s, "%d", value->u.ival);
838 if (s != NULL) {
839 np = sxml_set_node(ep, "int", s);
840 free(s);
841 }
842 break;
843 case SXMLRPC_VALUE_DOUBLE:
844 asprintf(&s, "%f", value->u.dval);
845 if (s != NULL) {
846 np = sxml_set_node(ep, "double", s);
847 free(s);
848 }
849 break;
850 case SXMLRPC_VALUE_BOOLEAN:
851 asprintf(&s, "%d", value->u.bval);
852 if (s != NULL) {
853 np = sxml_set_node(ep, "boolean", s);
854 free(s);
855 }
856 break;
857 case SXMLRPC_VALUE_STRING:
858 np = sxml_set_node(ep, "string", value->u.sval);
859 break;
860 case SXMLRPC_VALUE_DATETIME:
861 np = sxml_set_node(ep, "dateTime.iso8601", value->u.sval);
862 break;
863 case SXMLRPC_VALUE_BASE64:
864 np = sxml_set_node(ep, "base64", value->u.sval);
865 break;
866 case SXMLRPC_VALUE_STRUCT:
867 np = sxml_new_element(ep, "struct");
868 if (np != NULL) {
869 register size_t i;
870
871 for (i = 0; i < value->u.tval.size; i++) {
872 sxml_node_t * mp;
873
874 mp = sxml_new_element(np, "member");
875 if (mp != NULL) {
876 sxml_set_node(mp, "name", value->u.tval.member[i].name);
877 make_new_value(mp, &value->u.tval.member[i].value);
878 }
879 }
880 }
881 break;
882 case SXMLRPC_VALUE_ARRAY:
883 np = sxml_new_element(ep, "array");
884 if (np != NULL) {
885 sxml_node_t * dp;
886
887 dp = sxml_new_element(np, "data");
888 if (dp != NULL) {
889 register size_t i;
890
891 for (i = 0; i < value->u.aval.size; i++) {
892 make_new_value(dp, &value->u.aval.value[i]);
893 }
894 }
895 }
896 break;
897 default:
898 break;
899 }
900 return np != NULL ? 0 : -1;
901 }
902
903 return -1;
904 }
905
906 static int
get_call_params(sxRPC,root)907 get_call_params(sxRPC, root)
908 sxmlrpc_t * sxRPC;
909 sxml_node_t * root;
910 {
911 register sxml_node_t * np;
912
913 sxRPC->role = SXMLRPC_ROLE_SERVER;
914 sxRPC->method = SXMLRPC_METHOD_NONE;
915
916 np = sxml_find_element(root, "methodCall", NULL, NULL);
917 if (np != NULL) {
918 for (np = np->child; np != NULL; np = np->next) {
919 const char * content;
920
921 if (np->type != SXML_ELEMENT) { continue; }
922 if (np->value.element.name == NULL) { continue; }
923
924 content = sxml_get_content(np->child);
925 if (strcmp(np->value.element.name, "methodName") == 0) {
926 sxRPC->call_method = strdup(content);
927 }
928 else if (strcmp(np->value.element.name, "params") == 0) {
929 return set_call_params(sxRPC, np->child) > 0 ? 0 : -1;
930 }
931 }
932 }
933
934 return -1;
935 }
936
937 static size_t
set_call_params(sxRPC,node)938 set_call_params(sxRPC, node)
939 sxmlrpc_t * sxRPC;
940 sxml_node_t * node;
941 {
942 size_t status;
943
944 status = sxRPC->call_params.size = count_children(node);
945 if (sxRPC->call_params.size > 0) {
946 sxRPC->call_params.param
947 = (sxmlrpc_param_t *)calloc(sxRPC->call_params.size,
948 sizeof(sxmlrpc_param_t));
949 if (sxRPC->call_params.param != NULL) {
950 register sxml_node_t * np;
951 register size_t i;
952
953 for (np = node, i = 0; np != NULL && i < sxRPC->call_params.size;
954 np = np->next, i++) {
955 if (np->child != NULL &&
956 strcmp(np->child->value.element.name, "value") == 0) {
957 set_value(&sxRPC->call_params.param[i].value, np->child->child);
958 }
959 }
960 }
961 }
962
963 return status;
964 }
965
966 static sxml_node_t *
get_response_value(sxRPC,root)967 get_response_value(sxRPC, root)
968 sxmlrpc_t * sxRPC;
969 sxml_node_t * root;
970 {
971 register sxml_node_t * np;
972
973 np = sxml_find_element(root, "methodResponse", NULL, NULL);
974 if (np != NULL) {
975 np = np->child;
976 if (np != NULL) {
977 if (strcmp(np->value.element.name, "params") == 0) {
978 np = np->child;
979 if (np != NULL && strcmp(np->value.element.name, "param") == 0) {
980 np = np->child;
981 if (np != NULL && strcmp(np->value.element.name, "value") == 0) {
982 sxmlrpc_response_ok(sxRPC);
983 return np->child;
984 }
985 }
986 }
987 else if (strcmp(np->value.element.name, "fault") == 0) {
988 np = np->child;
989 if (np != NULL && strcmp(np->value.element.name, "value") == 0) {
990 sxmlrpc_response_fault(sxRPC);
991 return np->child;
992 }
993 }
994 }
995 }
996
997 return NULL;
998 }
999
1000 static int
set_value(v,node)1001 set_value(v, node)
1002 sxmlrpc_value_t * v;
1003 sxml_node_t * node;
1004 {
1005 register sxml_node_t * np;
1006
1007 for (np = node; np != NULL; np = np->next) {
1008 const char * content;
1009
1010 if (np->type != SXML_ELEMENT) { continue; }
1011 if (np->value.element.name == NULL) { continue; }
1012
1013 content = sxml_get_content(np->child);
1014 if (strcmp(np->value.element.name, "i4") == 0 ||
1015 strcmp(np->value.element.name, "int") == 0) {
1016 v->type = SXMLRPC_VALUE_INTEGER;
1017 v->u.ival = (sxmlrpc_int_t)strtol(content, (char **)NULL, 10);
1018 }
1019 else if (strcmp(np->value.element.name, "double") == 0) {
1020 v->type = SXMLRPC_VALUE_DOUBLE;
1021 v->u.dval = (sxmlrpc_double_t)strtod(content, (char **)NULL);
1022 }
1023 else if (strcmp(np->value.element.name, "boolean") == 0) {
1024 v->type = SXMLRPC_VALUE_BOOLEAN;
1025 v->u.bval = (sxmlrpc_boolean_t)strtol(content, (char **)NULL, 10);
1026 }
1027 else if (strcmp(np->value.element.name, "string") == 0) {
1028 v->type = SXMLRPC_VALUE_STRING;
1029 v->u.sval = (sxmlrpc_string_t)strdup(content);
1030 }
1031 else if (strcmp(np->value.element.name, "dateTime.iso8601") == 0) {
1032 v->type = SXMLRPC_VALUE_DATETIME;
1033 v->u.sval = (sxmlrpc_string_t)strdup(content);
1034 }
1035 else if (strcmp(np->value.element.name, "base64") == 0) {
1036 v->type = SXMLRPC_VALUE_BASE64;
1037 v->u.sval = (sxmlrpc_string_t)strdup(content);
1038 }
1039 else if (strcmp(np->value.element.name, "struct") == 0) {
1040 sxmlrpc_struct_t tval;
1041
1042 tval.size = count_children(np->child);
1043 if (tval.size > 0) {
1044 tval.member = (sxmlrpc_member_t *)calloc(tval.size,
1045 sizeof(sxmlrpc_member_t));
1046 if (tval.member != NULL) {
1047 set_value_member(tval.member, np->child);
1048 }
1049 }
1050 v->type = SXMLRPC_VALUE_STRUCT;
1051 v->u.tval = tval;
1052 }
1053 else if (strcmp(np->value.element.name, "array") == 0) {
1054 np = np->child;
1055 if (np != NULL && strcmp(np->value.element.name, "data") == 0) {
1056 sxmlrpc_array_t aval;
1057
1058 aval.size = count_children(np->child);
1059 if (aval.size > 0) {
1060 aval.value = (sxmlrpc_value_t *)calloc(aval.size,
1061 sizeof(sxmlrpc_value_t));
1062 if (aval.value != NULL) {
1063 set_value_array(aval.value, np->child);
1064 }
1065 }
1066 v->type = SXMLRPC_VALUE_ARRAY;
1067 v->u.aval = aval;
1068 }
1069 }
1070 else {
1071 return -1; /* error */
1072 }
1073 }
1074
1075 return 0;
1076 }
1077
1078 static int
set_value_member(m,node)1079 set_value_member(m, node)
1080 sxmlrpc_member_t * m;
1081 sxml_node_t * node;
1082 {
1083 register sxml_node_t * np;
1084 register int i = 0;
1085
1086 for (np = node; np != NULL; np = np->next) {
1087 if (np->type != SXML_ELEMENT) { continue; }
1088 if (np->value.element.name == NULL) { continue; }
1089
1090 if (strcmp(np->value.element.name, "member") == 0) {
1091 register sxml_node_t * mp;
1092
1093 for (mp = np->child; mp != NULL; mp = mp->next) {
1094 const char * content;
1095
1096 content = sxml_get_content(mp->child);
1097 if (strcmp(mp->value.element.name, "name") == 0 && content != NULL) {
1098 m[i].name = strdup(content);
1099 }
1100 else if (strcmp(mp->value.element.name, "value") == 0) {
1101 set_value(&m[i].value, mp->child);
1102 }
1103 }
1104 i++;
1105 }
1106 }
1107
1108 return 0;
1109 }
1110
1111 static int
set_value_array(v,node)1112 set_value_array(v, node)
1113 sxmlrpc_value_t * v;
1114 sxml_node_t * node;
1115 {
1116 register sxml_node_t * np;
1117 register int i = 0;
1118
1119 for (np = node; np != NULL; np = np->next) {
1120 if (np->type != SXML_ELEMENT) { continue; }
1121 if (np->value.element.name == NULL) { continue; }
1122
1123 if (strcmp(np->value.element.name, "value") == 0) {
1124 set_value(&v[i], np->child);
1125 i++;
1126 }
1127 }
1128
1129 return 0;
1130 }
1131
1132 static size_t
count_children(node)1133 count_children(node)
1134 sxml_node_t * node;
1135 {
1136 register sxml_node_t * np;
1137 register size_t c;
1138
1139 for (c = 0, np = node; np != NULL; np = np->next, c++) {
1140 ; /* nothing to do */
1141 }
1142
1143 return c;
1144 }
1145
1146 /*****************************************************************************/
1147
1148 int
sxmlrpc_set_value_int(value,ival)1149 sxmlrpc_set_value_int(value, ival)
1150 sxmlrpc_value_t * value;
1151 sxmlrpc_int_t ival;
1152 {
1153 if (value == NULL) {
1154 errno = EINVAL;
1155 return -1;
1156 }
1157
1158 value->type = SXMLRPC_VALUE_INTEGER;
1159 value->u.ival = ival;
1160
1161 return 0;
1162 }
1163
1164 int
sxmlrpc_set_value_double(value,dval)1165 sxmlrpc_set_value_double(value, dval)
1166 sxmlrpc_value_t * value;
1167 sxmlrpc_double_t dval;
1168 {
1169 if (value == NULL) {
1170 errno = EINVAL;
1171 return -1;
1172 }
1173
1174 value->type = SXMLRPC_VALUE_DOUBLE;
1175 value->u.dval = dval;
1176
1177 return 0;
1178 }
1179
1180 int
sxmlrpc_set_value_boolean(value,bval)1181 sxmlrpc_set_value_boolean(value, bval)
1182 sxmlrpc_value_t * value;
1183 sxmlrpc_boolean_t bval;
1184 {
1185 if (value == NULL) {
1186 errno = EINVAL;
1187 return -1;
1188 }
1189
1190 value->type = SXMLRPC_VALUE_BOOLEAN;
1191 value->u.bval = bval;
1192
1193 return 0;
1194 }
1195
1196 int
sxmlrpc_set_value_string(value,sval)1197 sxmlrpc_set_value_string(value, sval)
1198 sxmlrpc_value_t * value;
1199 sxmlrpc_string_t sval;
1200 {
1201 if (value == NULL) {
1202 errno = EINVAL;
1203 return -1;
1204 }
1205
1206 value->type = SXMLRPC_VALUE_STRING;
1207 value->u.sval = strdup(sval);
1208
1209 return 0;
1210 }
1211
1212 int
sxmlrpc_set_value_datetime(value,sval)1213 sxmlrpc_set_value_datetime(value, sval)
1214 sxmlrpc_value_t * value;
1215 sxmlrpc_string_t sval;
1216 {
1217 if (value == NULL) {
1218 errno = EINVAL;
1219 return -1;
1220 }
1221
1222 value->type = SXMLRPC_VALUE_DATETIME;
1223 value->u.sval = strdup(sval);
1224
1225 return 0;
1226 }
1227
1228 int
sxmlrpc_set_value_base64(value,sval)1229 sxmlrpc_set_value_base64(value, sval)
1230 sxmlrpc_value_t * value;
1231 sxmlrpc_string_t sval;
1232 {
1233 if (value == NULL) {
1234 errno = EINVAL;
1235 return -1;
1236 }
1237
1238 value->type = SXMLRPC_VALUE_BASE64;
1239 value->u.sval = strdup(sval);
1240
1241 return 0;
1242 }
1243
1244 int
sxmlrpc_set_value_struct(value,tval)1245 sxmlrpc_set_value_struct(value, tval)
1246 sxmlrpc_value_t * value;
1247 sxmlrpc_struct_t tval;
1248 {
1249 if (value == NULL) {
1250 errno = EINVAL;
1251 return -1;
1252 }
1253
1254 value->type = SXMLRPC_VALUE_STRUCT;
1255 value->u.tval = tval;
1256
1257 return 0;
1258 }
1259
1260 int
sxmlrpc_set_value_array(value,aval)1261 sxmlrpc_set_value_array(value, aval)
1262 sxmlrpc_value_t * value;
1263 sxmlrpc_array_t aval;
1264 {
1265 if (value == NULL) {
1266 errno = EINVAL;
1267 return -1;
1268 }
1269
1270 value->type = SXMLRPC_VALUE_ARRAY;
1271 value->u.aval = aval;
1272
1273 return 0;
1274 }
1275
1276
1277 int
sxmlrpc_set_param(param,value)1278 sxmlrpc_set_param(param, value)
1279 sxmlrpc_param_t * param;
1280 sxmlrpc_value_t value;
1281 {
1282 if (param == NULL) {
1283 errno = EINVAL;
1284 return -1;
1285 }
1286
1287 param->value = value;
1288
1289 return 0;
1290 }
1291
1292 int
sxmlrpc_set_fault(param,code,string)1293 sxmlrpc_set_fault(param, code, string)
1294 sxmlrpc_param_t * param;
1295 int code;
1296 sxmlrpc_string_t string;
1297 {
1298 sxmlrpc_member_t * mval;
1299
1300 mval = (sxmlrpc_member_t *)calloc(2, sizeof(sxmlrpc_member_t));
1301 if (mval != NULL) {
1302 mval[0].name = strdup("faultCode");
1303 sxmlrpc_set_value_int(&mval[0].value, code);
1304 mval[1].name = strdup("faultString");
1305 sxmlrpc_set_value_string(&mval[1].value, string);
1306 param->value.u.tval.size = 2;
1307 param->value.u.tval.member = mval;
1308 }
1309 else {
1310 param->value.u.tval.size = 0;
1311 param->value.u.tval.member = NULL;
1312 }
1313 param->value.type = SXMLRPC_VALUE_STRUCT;
1314
1315 return -1; /* fixed value returns */
1316 }
1317
1318 /*****************************************************************************/
1319
1320 int
sxmlrpc_get_fault_code(sxRPC)1321 sxmlrpc_get_fault_code(sxRPC)
1322 sxmlrpc_t * sxRPC;
1323 {
1324 return (sxRPC->method == SXMLRPC_METHOD_RESPONSE_FAULT)
1325 ? sxRPC->fault_code
1326 : 0;
1327 }
1328
1329 sxmlrpc_string_t
sxmlrpc_get_fault_string(sxRPC)1330 sxmlrpc_get_fault_string(sxRPC)
1331 sxmlrpc_t * sxRPC;
1332 {
1333 return (sxRPC->method == SXMLRPC_METHOD_RESPONSE_FAULT)
1334 ? sxRPC->fault_string
1335 : NULL;
1336 }
1337
1338 sxmlrpc_value_t *
sxmlrpc_get_response_value(sxRPC)1339 sxmlrpc_get_response_value(sxRPC)
1340 sxmlrpc_t * sxRPC;
1341 {
1342 return (sxRPC->method == SXMLRPC_METHOD_RESPONSE)
1343 ? &sxRPC->response_value
1344 : NULL;
1345 }
1346
1347 void
sxmlrpc_print_value(v,fout)1348 sxmlrpc_print_value(v, fout)
1349 sxmlrpc_value_t * v;
1350 register FILE * fout;
1351 {
1352 switch (sxmlrpc_get_value_type(v)) {
1353 case SXMLRPC_VALUE_INTEGER:
1354 fprintf(fout, "%d\n", sxmlrpc_get_value_int(v));
1355 break;
1356 case SXMLRPC_VALUE_DOUBLE:
1357 fprintf(fout, "%f\n", sxmlrpc_get_value_double(v));
1358 break;
1359 case SXMLRPC_VALUE_BOOLEAN:
1360 fprintf(fout, "%d\n", sxmlrpc_get_value_boolean(v));
1361 break;
1362 case SXMLRPC_VALUE_STRING:
1363 fprintf(fout, "%s\n", sxmlrpc_get_value_string(v));
1364 break;
1365 case SXMLRPC_VALUE_DATETIME:
1366 fprintf(fout, "%s\n", sxmlrpc_get_value_datetime(v));
1367 break;
1368 case SXMLRPC_VALUE_BASE64:
1369 fprintf(fout, "%s\n", sxmlrpc_get_value_base64(v));
1370 break;
1371 case SXMLRPC_VALUE_STRUCT: {
1372 sxmlrpc_member_t * mval;
1373 register size_t i;
1374
1375 mval = sxmlrpc_get_struct_member(v);
1376 for (i = 0; i < sxmlrpc_get_struct_size(v); i++) {
1377 fprintf(fout, "%s:\t", mval[i].name);
1378 sxmlrpc_print_value(&mval[i].value, fout);
1379 }
1380 }
1381 break;
1382 case SXMLRPC_VALUE_ARRAY: {
1383 sxmlrpc_value_t * val;
1384 register size_t i;
1385
1386 val = sxmlrpc_get_array_value(v);
1387 for (i = 0; i < sxmlrpc_get_array_size(v); i++) {
1388 sxmlrpc_print_value(&val[i], fout);
1389 }
1390 }
1391 default:
1392 break;
1393 }
1394 }
1395
1396 void
sxmlrpc_copy_value(dst,src)1397 sxmlrpc_copy_value(dst, src)
1398 sxmlrpc_value_t * dst;
1399 sxmlrpc_value_t * src;
1400 {
1401 dst->type = src->type;
1402 switch (src->type) {
1403 case SXMLRPC_VALUE_INTEGER:
1404 dst->u.ival = src->u.ival;
1405 break;
1406 case SXMLRPC_VALUE_DOUBLE:
1407 dst->u.dval = src->u.dval;
1408 break;
1409 case SXMLRPC_VALUE_BOOLEAN:
1410 dst->u.bval = src->u.bval;
1411 break;
1412 case SXMLRPC_VALUE_STRING:
1413 case SXMLRPC_VALUE_DATETIME:
1414 case SXMLRPC_VALUE_BASE64:
1415 dst->u.sval = strdup(src->u.sval);
1416 break;
1417 case SXMLRPC_VALUE_STRUCT:
1418 dst->u.tval.size = src->u.tval.size;
1419 dst->u.tval.member = (sxmlrpc_member_t *)calloc(src->u.tval.size,
1420 sizeof(sxmlrpc_member_t));
1421 if (dst->u.tval.member != NULL) {
1422 register size_t i;
1423
1424 for (i = 0; i < src->u.tval.size; i++) {
1425 dst->u.tval.member[i].name = strdup(src->u.tval.member[i].name);
1426 sxmlrpc_copy_value(&dst->u.tval.member[i].value,
1427 &src->u.tval.member[i].value);
1428 }
1429 }
1430 break;
1431 case SXMLRPC_VALUE_ARRAY:
1432 dst->u.aval.size = src->u.aval.size;
1433 dst->u.aval.value = (sxmlrpc_value_t *)calloc(src->u.tval.size,
1434 sizeof(sxmlrpc_value_t));
1435 if (dst->u.aval.value != NULL) {
1436 register size_t i;
1437
1438 for (i = 0; i < src->u.aval.size; i++) {
1439 sxmlrpc_copy_value(&dst->u.aval.value[i], &src->u.aval.value[i]);
1440 }
1441 }
1442 break;
1443 default:
1444 break;
1445 }
1446 }
1447
1448 /*****************************************************************************/
1449
1450 static netfd_t *
netfd_open(path,flags,mode)1451 netfd_open(path, flags, mode)
1452 const char * path;
1453 int flags;
1454 mode_t mode;
1455 {
1456 int fd;
1457 netfd_t * newfd;
1458
1459 while ((fd = open(path, flags, mode)) < 0) {
1460 if (errno != EINTR) {
1461 return NULL;
1462 }
1463 }
1464
1465 newfd = netfd_new(fd);
1466 if (newfd == NULL) {
1467 my_close(fd);
1468 }
1469
1470 return newfd;
1471 }
1472
1473 static netfd_t *
netfd_fdopen(osfd)1474 netfd_fdopen(osfd)
1475 int osfd;
1476 {
1477 return (osfd > 0) ? netfd_new(osfd) : NULL;
1478 }
1479
1480 static netfd_t *
netfd_new(osfd)1481 netfd_new(osfd)
1482 int osfd;
1483 {
1484 netfd_t * nfd;
1485
1486 nfd = (netfd_t *)malloc(sizeof(netfd_t));
1487 if (nfd != NULL) {
1488 nfd->osfd = osfd;
1489 nfd->rb.total = 0;
1490 nfd->rb.bufp = nfd->rb.buf;
1491 memset(nfd->rb.buf, 0, sizeof(nfd->rb.buf));
1492 }
1493
1494 return nfd;
1495 }
1496
1497 static int
netfd_close(nfd)1498 netfd_close(nfd)
1499 register netfd_t * nfd;
1500 {
1501 int status = -1;
1502
1503 if (nfd == NULL) {
1504 errno = EINVAL;
1505 }
1506 else {
1507 status = my_close(nfd->osfd);
1508 free(nfd);
1509 }
1510
1511 return status;
1512 }
1513
1514 static off_t
netfd_seek(nfd,offset,whence)1515 netfd_seek(nfd, offset, whence)
1516 register netfd_t * nfd;
1517 off_t offset;
1518 int whence;
1519 {
1520 struct stat sbuf;
1521
1522 if (fstat(nfd->osfd, &sbuf) == 0 && S_ISREG(sbuf.st_mode)) {
1523 off_t pos;
1524
1525 pos = lseek(nfd->osfd, offset, whence);
1526 if (pos != -1) {
1527 return pos;
1528 }
1529 errno = EINVAL;
1530 }
1531
1532 return -1;
1533 }
1534
1535 static ssize_t
netfd_read(nfd,buf,nbytes)1536 netfd_read(nfd, buf, nbytes)
1537 netfd_t * nfd;
1538 void * buf;
1539 size_t nbytes;
1540 {
1541 register ssize_t n = 0;
1542 register char * ptr = (char *)buf;
1543
1544 do {
1545 if (netfd_readbuf(nfd) < 0) { return -1; }
1546 if (nfd->rb.total == 0) { break; }
1547 *ptr++ = *nfd->rb.bufp++;
1548 nfd->rb.total--;
1549 } while ((size_t)n++ < nbytes && nfd->rb.total > 0);
1550
1551 return n;
1552 }
1553
1554 static ssize_t
netfd_write(nfd,buf,nbyte)1555 netfd_write(nfd, buf, nbyte)
1556 netfd_t * nfd;
1557 const void * buf;
1558 size_t nbyte;
1559 {
1560 size_t resid = nbyte;
1561 ssize_t n;
1562
1563 while (resid > 0) {
1564 n = write(nfd->osfd, buf, resid);
1565 if (n == -1) {
1566 if (errno == EINTR) { continue; }
1567 return -1;
1568 }
1569 else {
1570 resid -= n;
1571 if (resid == 0) { break; }
1572 buf = (const void *)((const char *)buf + n);
1573 }
1574 }
1575
1576 return (ssize_t)(nbyte - resid);
1577 }
1578
1579 static ssize_t
netfd_readline(nfd,buf,maxlen)1580 netfd_readline(nfd, buf, maxlen)
1581 netfd_t * nfd;
1582 void * buf;
1583 size_t maxlen;
1584 {
1585 register ssize_t n;
1586 register char * ptr = (char *)buf;
1587
1588 for (n = 1; (size_t)n < maxlen; n++) {
1589 char c;
1590 int status;
1591
1592 status = one_read(nfd, &c);
1593 if (status == 1) {
1594 *ptr++ = c;
1595 if (c == LF) { break; }
1596 if (c == EOL) { return 0; } /* EOF?, null data read */
1597 }
1598 else if (status == 0) {
1599 if (n == 1) { return 0; } /* EOF, no data read */
1600 else { break; } /* EOF, some data was read */
1601 }
1602 else {
1603 return -1; /* error */
1604 }
1605 }
1606 *ptr = EOL;
1607
1608 return n;
1609 }
1610
1611 static ssize_t
one_read(nfd,ptr)1612 one_read(nfd, ptr)
1613 netfd_t * nfd;
1614 char * ptr;
1615 {
1616 if (netfd_readbuf(nfd) < 0) { return -1; }
1617 if (nfd->rb.total == 0) { return 0; }
1618 nfd->rb.total--;
1619 *ptr = *nfd->rb.bufp++;
1620
1621 return 1;
1622 }
1623
1624 static int
netfd_readbuf(nfd)1625 netfd_readbuf(nfd)
1626 netfd_t * nfd;
1627 {
1628 if (nfd->rb.total <= 0) {
1629 memset(nfd->rb.buf, 0, sizeof(nfd->rb.buf));
1630 errno = 0;
1631 while ((nfd->rb.total = read(nfd->osfd,
1632 nfd->rb.buf, sizeof(nfd->rb.buf))) < 0) {
1633 if (errno == EINTR) { continue; }
1634 return -1;
1635 }
1636 nfd->rb.bufp = nfd->rb.buf;
1637 }
1638
1639 return nfd->rb.total;
1640 }
1641
1642 static netfd_t *
netfd_mkstemp(template)1643 netfd_mkstemp(template)
1644 char * template;
1645 {
1646 int fd;
1647
1648 fd = mkstemp(template);
1649 return (fd == -1) ? NULL : netfd_new(fd);
1650 }
1651
1652
1653 #if HAVE_FREEBSD_SENDFILE
1654 static int
netfd_sendfile(nfd,nsd,init_offset,nbytes,hdtr,ret_sbytes,flags)1655 netfd_sendfile(nfd, nsd, init_offset, nbytes, hdtr, ret_sbytes, flags)
1656 netfd_t * nfd;
1657 netfd_t * nsd;
1658 off_t init_offset;
1659 size_t nbytes;
1660 struct sf_hdtr * hdtr;
1661 off_t * ret_sbytes;
1662 int flags;
1663 {
1664 off_t offset;
1665 off_t sbytes;
1666
1667 offset = init_offset;
1668 while (sendfile(nfd->osfd, nsd->osfd, offset, nbytes, hdtr, &sbytes,
1669 flags) < 0) {
1670 offset += sbytes;
1671 nbytes -= sbytes;
1672 if (errno == EINTR) { continue; }
1673 return -1;
1674 }
1675 if (ret_sbytes != NULL) {
1676 *ret_sbytes = offset + sbytes;
1677 }
1678
1679 return 0;
1680 }
1681 #else
1682 #if HAVE_LINUX_SENDFILE
1683 /*
1684 * I have no linux environments. Is this routine ok?
1685 */
1686 static int
netfd_sendfile(nfd,nsd,init_offset,nbytes,hdtr,ret_sbytes,flags)1687 netfd_sendfile(nfd, nsd, init_offset, nbytes, hdtr, ret_sbytes, flags)
1688 netfd_t * nfd;
1689 netfd_t * nsd;
1690 off_t init_offset;
1691 size_t nbytes;
1692 void * hdtr;
1693 off_t * ret_sbytes;
1694 int flags;
1695 {
1696 off_t offset;
1697 off_t sbytes;
1698
1699 offset = init_offset;
1700 while (sendfile(nfd->osfd, nsd->osfd, &sbytes, nbytes) < 0) {
1701 offset += sbytes;
1702 nbytes -= sbytes;
1703 if (errno == EINTR) { continue; }
1704 return -1;
1705 }
1706 if (ret_sbytes != NULL) {
1707 *ret_sbytes = offset + sbytes;
1708 }
1709
1710 return 0;
1711 }
1712 #else /* No sendfile(2) */
1713 static int
netfd_sendfile(nfd,nsd,offset,nbytes,hdtr,sbytes,flags)1714 netfd_sendfile(nfd, nsd, offset, nbytes, hdtr, sbytes, flags)
1715 netfd_t * nfd;
1716 netfd_t * nsd;
1717 off_t offset;
1718 size_t nbytes;
1719 void * hdtr; // unused
1720 off_t * sbytes;
1721 int flags; // unused
1722 {
1723 void * buf;
1724 size_t len;
1725 ssize_t n;
1726 int status = 0;
1727
1728 if (nbytes == 0) {
1729 off_t off;
1730 /* get whole file size */
1731 off = netfd_seek(nfd, 0, NETFD_SEEK_END);
1732 if (off == -1) {
1733 return -1;
1734 }
1735 len = (size_t)off;
1736 }
1737 else {
1738 len = nbytes;
1739 }
1740 buf = mmap(NULL, len, PROT_READ, MAP_PRIVATE, nfd->osfd, offset);
1741 if (buf == MAP_FAILED) {
1742 return -1;
1743 }
1744 n = netfd_write(nsd, buf, len);
1745 if (n == -1) {
1746 status = -1;
1747 }
1748 if (sbytes != NULL) {
1749 *sbytes = (size_t)n;
1750 }
1751 munmap(buf, len);
1752
1753 return status;
1754 }
1755 #endif /* HAVE_LINUX_SENDFILE */
1756 #endif /* HAVE_FREEBSD_SENDFILE */
1757
1758 static void
sigalrm(signo)1759 sigalrm(signo)
1760 int signo; // unused
1761 {
1762 timedout = 1; /* set flag */
1763 }
1764
1765 static netfd_t *
netfd_tcp_client(hostname,service)1766 netfd_tcp_client(hostname, service)
1767 const char * hostname;
1768 const char * service;
1769 {
1770 struct addrinfo hints;
1771 struct addrinfo * res;
1772
1773 memset((char *)&hints, 0, sizeof(hints));
1774 hints.ai_family = AF_UNSPEC;
1775 hints.ai_socktype = SOCK_STREAM;
1776 hints.ai_protocol = IPPROTO_TCP;
1777 hints.ai_flags = 0;
1778
1779 if (getaddrinfo(hostname, service, &hints, &res) == 0) {
1780 struct itimerval value; /* new */
1781 struct itimerval ovalue; /* old */
1782 struct sigaction act; /* new */
1783 struct sigaction oact; /* old */
1784 struct addrinfo * res_save;
1785 int sd;
1786
1787 #define DEF_CONNECT_TIMEOUT (10000) /* msec */
1788 sigemptyset(&act.sa_mask);
1789 act.sa_flags = 0;
1790 act.sa_handler = (void *)sigalrm;
1791 sigaction(SIGALRM, &act, &oact);
1792 value.it_interval.tv_sec = value.it_interval.tv_usec = 0;
1793 value.it_value.tv_sec = DEF_CONNECT_TIMEOUT / 1000;
1794 value.it_value.tv_usec = (DEF_CONNECT_TIMEOUT % 1000) * 1000;
1795 setitimer(ITIMER_REAL, &value, &ovalue);
1796 timedout = 0; /* clear flag */
1797
1798 res_save = res;
1799 do {
1800 errno = 0;
1801 /* create a socket */
1802 sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
1803 if (sd == -1) {
1804 continue; /*ignore this one */
1805 }
1806 /* initiate a connection on a socket */
1807 if (connect(sd, res->ai_addr, res->ai_addrlen) == 0) {
1808 break;
1809 }
1810 if (errno == EINTR) {
1811 if (timedout) { errno = ETIMEDOUT; }
1812 }
1813 my_close(sd); /* ignore this one */
1814 } while ((res = res->ai_next) != NULL && errno == 0);
1815 freeaddrinfo(res_save);
1816 sigaction(SIGALRM, &oact, NULL);
1817 setitimer(ITIMER_REAL, &ovalue, NULL);
1818
1819 if (res != NULL) {
1820 netfd_t * nfd;
1821
1822 nfd = netfd_fdopen(sd);
1823 if (nfd != NULL) {
1824 return nfd;
1825 }
1826 my_close(sd);
1827 }
1828 }
1829
1830 return NULL;
1831 }
1832
1833 static netfd_t *
netfd_tcp_server(hostname,service,backlog)1834 netfd_tcp_server(hostname, service, backlog)
1835 const char * hostname;
1836 const char * service;
1837 const int backlog;
1838 {
1839 struct addrinfo hints;
1840 struct addrinfo * res;
1841
1842 memset((char *)&hints, 0, sizeof(hints));
1843 hints.ai_family = AF_UNSPEC;
1844 hints.ai_socktype = SOCK_STREAM;
1845 hints.ai_protocol = IPPROTO_TCP;
1846 hints.ai_flags = AI_PASSIVE;
1847
1848 if (getaddrinfo(hostname, service, &hints, &res) == 0) {
1849 struct addrinfo * res_save;
1850 int sd;
1851
1852 res_save = res;
1853 do {
1854 static const int on = 1;
1855
1856 /* create a socket */
1857 sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
1858 if (sd < 0) {
1859 continue; /*error, try next one */
1860 }
1861 /* allow reuse of local address */
1862 (void)setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
1863 /* bind a socket */
1864 if (bind(sd, res->ai_addr, res->ai_addrlen) == 0) {
1865 break; /* success */
1866 }
1867 my_close(sd); /* bind error, close and try next one */
1868 } while ((res = res->ai_next) != NULL);
1869 freeaddrinfo(res_save);
1870
1871 if (res != NULL) {
1872 /* listen for connection on the socket */
1873 if (listen(sd, backlog > 0 ? backlog : NETFD_DEF_BACKLOG) == 0) {
1874 netfd_t * nfd;
1875
1876 nfd = netfd_fdopen(sd);
1877 if (nfd != NULL) {
1878 return nfd;
1879 }
1880 my_close(sd);
1881 }
1882 }
1883 }
1884
1885 return NULL;
1886 }
1887
1888 static netfd_t *
netfd_accept(nfd,addr,addrlen)1889 netfd_accept(nfd, addr, addrlen)
1890 netfd_t * nfd;
1891 struct sockaddr * addr;
1892 socklen_t * addrlen;
1893 {
1894 int sd;
1895 netfd_t * newfd;
1896
1897 #if 0
1898 while ((sd = accept(nfd->osfd, addr, (socklen_t *)addrlen)) < 0) {
1899 if (errno == EINTR) {
1900 continue;
1901 }
1902 return NULL;
1903 }
1904 #else
1905 if ((sd = accept(nfd->osfd, addr, addrlen)) < 0) {
1906 return NULL;
1907 }
1908 #endif
1909
1910 newfd = netfd_fdopen(sd);
1911 if (newfd == NULL) {
1912 my_close(sd);
1913 }
1914
1915 return newfd;
1916 }
1917
1918 static int
netfd_sock_ntop(sa0,ipaddr)1919 netfd_sock_ntop(sa0, ipaddr)
1920 const struct sockaddr * sa0;
1921 char ** ipaddr;
1922 {
1923 static char host[132]; /* Unix domain is largest */
1924 int status = -1;
1925
1926 memset(host, 0, sizeof(host));
1927 switch (sa0->sa_family) {
1928 case AF_INET: {
1929 struct sockaddr_in * sa = (struct sockaddr_in *)sa0;
1930
1931 if (inet_ntop(AF_INET, &sa->sin_addr, host, sizeof(host)) != NULL) {
1932 status = 0;
1933 }
1934 }
1935 break;
1936 case AF_INET6: {
1937 struct sockaddr_in6 * sa = (struct sockaddr_in6 *)sa0;
1938
1939 if (inet_ntop(AF_INET6, &sa->sin6_addr, host, sizeof(host)) != NULL) {
1940 status = 0;
1941 }
1942 }
1943 break;
1944 default:
1945 break;
1946 }
1947
1948 if (ipaddr != NULL) {
1949 if (status == 0) {
1950 *ipaddr = strdup(host);
1951 }
1952 else {
1953 *ipaddr = NULL;
1954 }
1955 }
1956
1957 return status;
1958 }
1959
1960 static int
my_close(fd)1961 my_close(fd)
1962 int fd;
1963 {
1964 int status;
1965 int saved_errno = errno;
1966 while (((status = close(fd)) < 0) && (errno == EINTR)) { continue; }
1967 errno = saved_errno;
1968 return status;
1969 }
1970
1971 /*****************************************************************************/
1972
1973 const char *
sxmlrpc_get_datetime_iso8601(t)1974 sxmlrpc_get_datetime_iso8601(t)
1975 const time_t t;
1976 {
1977 static char iso8601[sizeof("20060401T16:55:31")];
1978 struct tm * tp;
1979
1980 tp = localtime(&t);
1981 if (tp == NULL) {
1982 return NULL;
1983 }
1984 memset(iso8601, 0, sizeof(iso8601));
1985 snprintf(iso8601, sizeof(iso8601), "%04d%02d%02dT%02d:%02d:%02d",
1986 tp->tm_year + 1900, tp->tm_mon + 1, tp->tm_mday,
1987 tp->tm_hour, tp->tm_min, tp->tm_sec);
1988
1989 return iso8601;
1990 }
1991
1992 const char *
sxmlrpc_get_current_datetime_iso8601(void)1993 sxmlrpc_get_current_datetime_iso8601(void)
1994 {
1995 time_t now;
1996
1997 time(&now);
1998
1999 return sxmlrpc_get_datetime_iso8601(now);
2000 }
2001
2002 /*
2003 * bit sequence for mask
2004 *
2005 * 0xfc = 11111100
2006 * 0x03 = 00000011
2007 * 0xf0 = 11110000
2008 * 0x0f = 00001111
2009 * 0xc0 = 11000000
2010 * 0x3f = 00111111
2011 * 0x30 = 00110000
2012 * 0x3c = 00111100
2013 */
2014
2015 /*
2016 * Base64 alphabet
2017 */
2018 static const char base64[] =
2019 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
2020
2021 int
sxmlrpc_base64_encode(str,rbuf,rsize)2022 sxmlrpc_base64_encode(str, rbuf, rsize)
2023 const char * str;
2024 char * rbuf; /* return base64 encoded string */
2025 size_t rsize; /* return buffer size */
2026 {
2027 size_t len;
2028 register int i;
2029 register int n;
2030
2031 len = strlen(str);
2032 if (rsize < (size_t)((double)len * 1.33) + 1) {
2033 return -1;
2034 }
2035
2036 /*
2037 * encode 3-bytes (24-bits) at a time
2038 */
2039 memset(rbuf, 0, rsize);
2040 for (i = n = 0; i < len - (len % 3); i += 3, n += 4) {
2041 rbuf[n] = base64[( str[i] & 0xfc) >> 2];
2042 rbuf[n+1] = base64[((str[i] & 0x03) << 4) | ((str[i+1] & 0xf0) >> 4)];
2043 rbuf[n+2] = base64[((str[i+1] & 0x0f) << 2) | ((str[i+2] & 0xc0) >> 6)];
2044 rbuf[n+3] = base64[( str[i+2] & 0x3f)];
2045 }
2046
2047 i = len - (len % 3); /* rest size */
2048 switch (len % 3) {
2049 case 2: /* one character padding */
2050 rbuf[n] = base64[( str[i] & 0xfc) >> 2];
2051 rbuf[n+1] = base64[((str[i] & 0x03) << 4) | ((str[i+1] & 0xf0) >> 4)];
2052 rbuf[n+2] = base64[( str[i+1] & 0x0f) << 2];
2053 rbuf[n+3] = base64[64]; /* Pad */
2054 n += 4;
2055 break;
2056 case 1: /* two character padding */
2057 rbuf[n] = base64[(str[i] & 0xfc) >> 2];
2058 rbuf[n+1] = base64[(str[i] & 0x03) << 4];
2059 rbuf[n+2] = base64[64]; /* Pad */
2060 rbuf[n+3] = base64[64]; /* Pad */
2061 n += 4;
2062 break;
2063 default:
2064 break;
2065 }
2066 rbuf[n] = '\0';
2067
2068 return n;
2069 }
2070
2071 int
sxmlrpc_base64_decode(str,rbuf,rsize)2072 sxmlrpc_base64_decode(str, rbuf, rsize)
2073 const char * str;
2074 char * rbuf; /* return base64 decoded string */
2075 size_t rsize; /* return buffer size */
2076 {
2077 #define VAL(x) (str[(x)] == '=' ? 0 : strchr(base64, str[(x)]) - base64)
2078 size_t len;
2079 register int i;
2080 register int n;
2081
2082 len = strlen(str);
2083 if (rsize < (size_t)((double)len * 0.75) + 1) {
2084 return -1;
2085 }
2086
2087 /*
2088 * work on 4-words (24-bits) at a time
2089 */
2090 memset(rbuf, 0, rsize);
2091 for (i = n = 0; i < len; i += 4, n += 3) {
2092 rbuf[n] = (VAL(i) << 2) | ((VAL(i+1) & 0x30) >> 4);
2093 rbuf[n+1] = ((VAL(i+1) & 0x0f) << 4) | ((VAL(i+2) & 0x3c) >> 2);
2094 rbuf[n+2] = ((VAL(i+2) & 0x03) << 6) | (VAL(i+3) & 0x3f);
2095 }
2096 /* remove padding data */
2097 if (str[len - 1] == '=') { n--; }
2098 if (str[len - 2] == '=') { n--; }
2099
2100 return n;
2101 }
2102
2103 /*****************************************************************************/
2104
2105 int
sxmlrpc_get_call_params(sxRPC,infd)2106 sxmlrpc_get_call_params(sxRPC, infd)
2107 sxmlrpc_t * sxRPC;
2108 int infd;
2109 {
2110 sxml_node_t * root;
2111 int status = -1;
2112
2113 root = sxml_parse_file(infd);
2114 if (root != NULL) {
2115 status = get_call_params(sxRPC, root);
2116 sxml_delete_node(root);
2117 }
2118
2119 return status;
2120 }
2121
2122 int
sxmlrpc_set_response_param(sxRPC,param,outfd)2123 sxmlrpc_set_response_param(sxRPC, param, outfd)
2124 sxmlrpc_t * sxRPC;
2125 sxmlrpc_param_t * param;
2126 int outfd;
2127 {
2128 int stkfd;
2129 int status;
2130
2131 stkfd = sxRPC->msgbdy_fd;
2132 sxRPC->msgbdy_fd = outfd;
2133 status = make_response_body(sxRPC, param);
2134 sxRPC->msgbdy_fd = stkfd;
2135
2136 return status;
2137 }
2138
2139 void
sxmlrpc_set_encoding(sxRPC,ctype)2140 sxmlrpc_set_encoding(sxRPC, ctype)
2141 sxmlrpc_t * sxRPC;
2142 const char * ctype;
2143 {
2144 sxRPC->encoding = strdup(ctype);
2145 }
2146