OLD | NEW |
1 /* | 1 /* |
2 * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets. | 2 * nanohttp.c: minimalist HTTP GET implementation to fetch external subsets. |
3 * focuses on size, streamability, reentrancy and portability | 3 * focuses on size, streamability, reentrancy and portability |
4 * | 4 * |
5 * This is clearly not a general purpose HTTP implementation | 5 * This is clearly not a general purpose HTTP implementation |
6 * If you look for one, check: | 6 * If you look for one, check: |
7 * http://www.w3.org/Library/ | 7 * http://www.w3.org/Library/ |
8 * | 8 * |
9 * See Copyright for the status of this software. | 9 * See Copyright for the status of this software. |
10 * | 10 * |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 #endif | 47 #endif |
48 #ifdef HAVE_FCNTL_H | 48 #ifdef HAVE_FCNTL_H |
49 #include <fcntl.h> | 49 #include <fcntl.h> |
50 #endif | 50 #endif |
51 #ifdef HAVE_ERRNO_H | 51 #ifdef HAVE_ERRNO_H |
52 #include <errno.h> | 52 #include <errno.h> |
53 #endif | 53 #endif |
54 #ifdef HAVE_SYS_TIME_H | 54 #ifdef HAVE_SYS_TIME_H |
55 #include <sys/time.h> | 55 #include <sys/time.h> |
56 #endif | 56 #endif |
| 57 #ifndef HAVE_POLL_H |
57 #ifdef HAVE_SYS_SELECT_H | 58 #ifdef HAVE_SYS_SELECT_H |
58 #include <sys/select.h> | 59 #include <sys/select.h> |
59 #endif | 60 #endif |
| 61 #else |
| 62 #include <poll.h> |
| 63 #endif |
60 #ifdef HAVE_STRINGS_H | 64 #ifdef HAVE_STRINGS_H |
61 #include <strings.h> | 65 #include <strings.h> |
62 #endif | 66 #endif |
63 #ifdef SUPPORT_IP6 | 67 #ifdef SUPPORT_IP6 |
64 #include <resolv.h> | 68 #include <resolv.h> |
65 #endif | 69 #endif |
66 #ifdef HAVE_ZLIB_H | 70 #ifdef HAVE_ZLIB_H |
67 #include <zlib.h> | 71 #include <zlib.h> |
68 #endif | 72 #endif |
69 | 73 |
(...skipping 18 matching lines...) Expand all Loading... |
88 #include <libxml/xmlmemory.h> | 92 #include <libxml/xmlmemory.h> |
89 #include <libxml/parser.h> /* for xmlStr(n)casecmp() */ | 93 #include <libxml/parser.h> /* for xmlStr(n)casecmp() */ |
90 #include <libxml/nanohttp.h> | 94 #include <libxml/nanohttp.h> |
91 #include <libxml/globals.h> | 95 #include <libxml/globals.h> |
92 #include <libxml/uri.h> | 96 #include <libxml/uri.h> |
93 | 97 |
94 /** | 98 /** |
95 * A couple portability macros | 99 * A couple portability macros |
96 */ | 100 */ |
97 #ifndef _WINSOCKAPI_ | 101 #ifndef _WINSOCKAPI_ |
98 #ifndef __BEOS__ | 102 #if !defined(__BEOS__) || defined(__HAIKU__) |
99 #define closesocket(s) close(s) | 103 #define closesocket(s) close(s) |
100 #endif | 104 #endif |
101 #define SOCKET int | 105 #define SOCKET int |
102 #endif | 106 #endif |
103 | 107 |
104 #ifdef __BEOS__ | 108 #ifdef __BEOS__ |
105 #ifndef PF_INET | 109 #ifndef PF_INET |
106 #define PF_INET AF_INET | 110 #define PF_INET AF_INET |
107 #endif | 111 #endif |
108 #endif | 112 #endif |
(...skipping 30 matching lines...) Expand all Loading... |
139 int state; /* WRITE / READ / CLOSED */ | 143 int state; /* WRITE / READ / CLOSED */ |
140 char *out; /* buffer sent (zero terminated) */ | 144 char *out; /* buffer sent (zero terminated) */ |
141 char *outptr; /* index within the buffer sent */ | 145 char *outptr; /* index within the buffer sent */ |
142 char *in; /* the receiving buffer */ | 146 char *in; /* the receiving buffer */ |
143 char *content; /* the start of the content */ | 147 char *content; /* the start of the content */ |
144 char *inptr; /* the next byte to read from network */ | 148 char *inptr; /* the next byte to read from network */ |
145 char *inrptr; /* the next byte to give back to the client */ | 149 char *inrptr; /* the next byte to give back to the client */ |
146 int inlen; /* len of the input buffer */ | 150 int inlen; /* len of the input buffer */ |
147 int last; /* return code for last operation */ | 151 int last; /* return code for last operation */ |
148 int returnValue; /* the protocol return value */ | 152 int returnValue; /* the protocol return value */ |
| 153 int version; /* the protocol version */ |
149 int ContentLength; /* specified content length from HTTP header */ | 154 int ContentLength; /* specified content length from HTTP header */ |
150 char *contentType; /* the MIME type for the input */ | 155 char *contentType; /* the MIME type for the input */ |
151 char *location; /* the new URL in case of redirect */ | 156 char *location; /* the new URL in case of redirect */ |
152 char *authHeader; /* contents of {WWW,Proxy}-Authenticate header */ | 157 char *authHeader; /* contents of {WWW,Proxy}-Authenticate header */ |
153 char *encoding; /* encoding extracted from the contentType */ | 158 char *encoding; /* encoding extracted from the contentType */ |
154 char *mimeType; /* Mime-Type extracted from the contentType */ | 159 char *mimeType; /* Mime-Type extracted from the contentType */ |
155 #ifdef HAVE_ZLIB_H | 160 #ifdef HAVE_ZLIB_H |
156 z_stream *strm; /* Zlib stream object */ | 161 z_stream *strm; /* Zlib stream object */ |
157 int usesGzip; /* "Content-Encoding: gzip" was detected */ | 162 int usesGzip; /* "Content-Encoding: gzip" was detected */ |
158 #endif | 163 #endif |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
432 | 437 |
433 /** | 438 /** |
434 * xmlNanoHTTPSend: | 439 * xmlNanoHTTPSend: |
435 * @ctxt: an HTTP context | 440 * @ctxt: an HTTP context |
436 * | 441 * |
437 * Send the input needed to initiate the processing on the server side | 442 * Send the input needed to initiate the processing on the server side |
438 * Returns number of bytes sent or -1 on error. | 443 * Returns number of bytes sent or -1 on error. |
439 */ | 444 */ |
440 | 445 |
441 static int | 446 static int |
442 xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char * xmt_ptr, int outlen) { | 447 xmlNanoHTTPSend(xmlNanoHTTPCtxtPtr ctxt, const char *xmt_ptr, int outlen) |
| 448 { |
| 449 int total_sent = 0; |
| 450 #ifdef HAVE_POLL_H |
| 451 struct pollfd p; |
| 452 #else |
| 453 struct timeval tv; |
| 454 fd_set wfd; |
| 455 #endif |
443 | 456 |
444 int » total_sent = 0; | 457 if ((ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL)) { |
445 | |
446 if ( (ctxt->state & XML_NANO_HTTP_WRITE) && (xmt_ptr != NULL ) ) { | |
447 while (total_sent < outlen) { | 458 while (total_sent < outlen) { |
448 int nsent = send(ctxt->fd, xmt_ptr + total_sent, | 459 int nsent = send(ctxt->fd, xmt_ptr + total_sent, |
449 outlen - total_sent, 0); | 460 outlen - total_sent, 0); |
450 if (nsent>0) | 461 |
| 462 if (nsent > 0) |
451 total_sent += nsent; | 463 total_sent += nsent; |
452 » else if ( ( nsent == -1 ) && | 464 else if ((nsent == -1) && |
453 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK | 465 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK |
454 » » ( socket_errno( ) != EAGAIN ) && | 466 (socket_errno() != EAGAIN) && |
455 #endif | 467 #endif |
456 » » ( socket_errno( ) != EWOULDBLOCK ) ) { | 468 (socket_errno() != EWOULDBLOCK)) { |
457 » » __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n"); | 469 __xmlIOErr(XML_FROM_HTTP, 0, "send failed\n"); |
458 » » if ( total_sent == 0 ) | 470 if (total_sent == 0) |
459 » » total_sent = -1; | 471 total_sent = -1; |
460 » » break; | 472 break; |
461 » } | 473 } else { |
462 » else { | 474 /* |
463 » /* | 475 * No data sent |
464 » » ** No data sent | 476 * Since non-blocking sockets are used, wait for |
465 » » ** Since non-blocking sockets are used, wait for | 477 * socket to be writable or default timeout prior |
466 » » ** socket to be writable or default timeout prior | 478 * to retrying. |
467 » » ** to retrying. | 479 */ |
468 » » */ | 480 #ifndef HAVE_POLL_H |
| 481 #ifndef _WINSOCKAPI_ |
| 482 if (ctxt->fd > FD_SETSIZE) |
| 483 return -1; |
| 484 #endif |
469 | 485 |
470 » » struct timeval» tv; | 486 tv.tv_sec = timeout; |
471 » » fd_set» » wfd; | 487 tv.tv_usec = 0; |
472 | 488 FD_ZERO(&wfd); |
473 » » tv.tv_sec = timeout; | |
474 » » tv.tv_usec = 0; | |
475 » » FD_ZERO( &wfd ); | |
476 #ifdef _MSC_VER | 489 #ifdef _MSC_VER |
477 #pragma warning(push) | 490 #pragma warning(push) |
478 #pragma warning(disable: 4018) | 491 #pragma warning(disable: 4018) |
479 #endif | 492 #endif |
480 » » FD_SET( ctxt->fd, &wfd ); | 493 FD_SET(ctxt->fd, &wfd); |
481 #ifdef _MSC_VER | 494 #ifdef _MSC_VER |
482 #pragma warning(pop) | 495 #pragma warning(pop) |
483 #endif | 496 #endif |
484 » » (void)select( ctxt->fd + 1, NULL, &wfd, NULL, &tv ); | 497 (void) select(ctxt->fd + 1, NULL, &wfd, NULL, &tv); |
485 » } | 498 #else |
486 » } | 499 p.fd = ctxt->fd; |
| 500 p.events = POLLOUT; |
| 501 (void) poll(&p, 1, timeout * 1000); |
| 502 #endif /* !HAVE_POLL_H */ |
| 503 } |
| 504 } |
487 } | 505 } |
488 | 506 |
489 return total_sent; | 507 return total_sent; |
490 } | 508 } |
491 | 509 |
492 /** | 510 /** |
493 * xmlNanoHTTPRecv: | 511 * xmlNanoHTTPRecv: |
494 * @ctxt: an HTTP context | 512 * @ctxt: an HTTP context |
495 * | 513 * |
496 * Read information coming from the HTTP connection. | 514 * Read information coming from the HTTP connection. |
497 * This is a blocking call (but it blocks in select(), not read()). | 515 * This is a blocking call (but it blocks in select(), not read()). |
498 * | 516 * |
499 * Returns the number of byte read or -1 in case of error. | 517 * Returns the number of byte read or -1 in case of error. |
500 */ | 518 */ |
501 | 519 |
502 static int | 520 static int |
503 xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) { | 521 xmlNanoHTTPRecv(xmlNanoHTTPCtxtPtr ctxt) |
| 522 { |
| 523 #ifdef HAVE_POLL_H |
| 524 struct pollfd p; |
| 525 #else |
504 fd_set rfd; | 526 fd_set rfd; |
505 struct timeval tv; | 527 struct timeval tv; |
| 528 #endif |
506 | 529 |
507 | 530 |
508 while (ctxt->state & XML_NANO_HTTP_READ) { | 531 while (ctxt->state & XML_NANO_HTTP_READ) { |
509 » if (ctxt->in == NULL) { | 532 if (ctxt->in == NULL) { |
510 » ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char)); | 533 ctxt->in = (char *) xmlMallocAtomic(65000 * sizeof(char)); |
511 » if (ctxt->in == NULL) { | 534 if (ctxt->in == NULL) { |
512 » » xmlHTTPErrMemory("allocating input"); | 535 xmlHTTPErrMemory("allocating input"); |
513 » ctxt->last = -1; | 536 ctxt->last = -1; |
514 » » return(-1); | 537 return (-1); |
515 » } | 538 } |
516 » ctxt->inlen = 65000; | 539 ctxt->inlen = 65000; |
517 » ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in; | 540 ctxt->inptr = ctxt->content = ctxt->inrptr = ctxt->in; |
518 » } | 541 } |
519 » if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) { | 542 if (ctxt->inrptr > ctxt->in + XML_NANO_HTTP_CHUNK) { |
520 » int delta = ctxt->inrptr - ctxt->in; | 543 int delta = ctxt->inrptr - ctxt->in; |
521 » int len = ctxt->inptr - ctxt->inrptr; | 544 int len = ctxt->inptr - ctxt->inrptr; |
522 » | 545 |
523 » memmove(ctxt->in, ctxt->inrptr, len); | 546 memmove(ctxt->in, ctxt->inrptr, len); |
524 » ctxt->inrptr -= delta; | 547 ctxt->inrptr -= delta; |
525 » ctxt->content -= delta; | 548 ctxt->content -= delta; |
526 » ctxt->inptr -= delta; | 549 ctxt->inptr -= delta; |
527 » } | 550 } |
528 if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) { | 551 if ((ctxt->in + ctxt->inlen) < (ctxt->inptr + XML_NANO_HTTP_CHUNK)) { |
529 » int d_inptr = ctxt->inptr - ctxt->in; | 552 int d_inptr = ctxt->inptr - ctxt->in; |
530 » int d_content = ctxt->content - ctxt->in; | 553 int d_content = ctxt->content - ctxt->in; |
531 » int d_inrptr = ctxt->inrptr - ctxt->in; | 554 int d_inrptr = ctxt->inrptr - ctxt->in; |
532 » char *» tmp_ptr = ctxt->in; | 555 char *tmp_ptr = ctxt->in; |
533 | 556 |
534 » ctxt->inlen *= 2; | 557 ctxt->inlen *= 2; |
535 ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen); | 558 ctxt->in = (char *) xmlRealloc(tmp_ptr, ctxt->inlen); |
536 » if (ctxt->in == NULL) { | 559 if (ctxt->in == NULL) { |
537 » » xmlHTTPErrMemory("allocating input buffer"); | 560 xmlHTTPErrMemory("allocating input buffer"); |
538 » » xmlFree( tmp_ptr ); | 561 xmlFree(tmp_ptr); |
539 » ctxt->last = -1; | 562 ctxt->last = -1; |
540 » » return(-1); | 563 return (-1); |
541 » } | 564 } |
542 ctxt->inptr = ctxt->in + d_inptr; | 565 ctxt->inptr = ctxt->in + d_inptr; |
543 ctxt->content = ctxt->in + d_content; | 566 ctxt->content = ctxt->in + d_content; |
544 ctxt->inrptr = ctxt->in + d_inrptr; | 567 ctxt->inrptr = ctxt->in + d_inrptr; |
545 » } | 568 } |
546 » ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0); | 569 ctxt->last = recv(ctxt->fd, ctxt->inptr, XML_NANO_HTTP_CHUNK, 0); |
547 » if (ctxt->last > 0) { | 570 if (ctxt->last > 0) { |
548 » ctxt->inptr += ctxt->last; | 571 ctxt->inptr += ctxt->last; |
549 » return(ctxt->last); | 572 return (ctxt->last); |
550 » } | 573 } |
551 » if (ctxt->last == 0) { | 574 if (ctxt->last == 0) { |
552 » return(0); | 575 return (0); |
553 » } | 576 } |
554 » if (ctxt->last == -1) { | 577 if (ctxt->last == -1) { |
555 » switch (socket_errno()) { | 578 switch (socket_errno()) { |
556 » » case EINPROGRESS: | 579 case EINPROGRESS: |
557 » » case EWOULDBLOCK: | 580 case EWOULDBLOCK: |
558 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK | 581 #if defined(EAGAIN) && EAGAIN != EWOULDBLOCK |
559 » » case EAGAIN: | 582 case EAGAIN: |
560 #endif | 583 #endif |
561 » » break; | 584 break; |
562 | 585 |
563 » » case ECONNRESET: | 586 case ECONNRESET: |
564 » » case ESHUTDOWN: | 587 case ESHUTDOWN: |
565 » » return ( 0 ); | 588 return (0); |
566 | 589 |
567 » » default: | 590 default: |
568 » » __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n"); | 591 __xmlIOErr(XML_FROM_HTTP, 0, "recv failed\n"); |
569 » » return(-1); | 592 return (-1); |
570 » } | 593 } |
571 » } | 594 } |
| 595 #ifdef HAVE_POLL_H |
| 596 p.fd = ctxt->fd; |
| 597 p.events = POLLIN; |
| 598 if ((poll(&p, 1, timeout * 1000) < 1) |
| 599 #if defined(EINTR) |
| 600 && (errno != EINTR) |
| 601 #endif |
| 602 ) |
| 603 return (0); |
| 604 #else /* !HAVE_POLL_H */ |
| 605 #ifndef _WINSOCKAPI_ |
| 606 if (ctxt->fd > FD_SETSIZE) |
| 607 return 0; |
| 608 #endif |
572 | 609 |
573 » tv.tv_sec = timeout; | 610 tv.tv_sec = timeout; |
574 » tv.tv_usec = 0; | 611 tv.tv_usec = 0; |
575 » FD_ZERO(&rfd); | 612 FD_ZERO(&rfd); |
| 613 |
576 #ifdef _MSC_VER | 614 #ifdef _MSC_VER |
577 #pragma warning(push) | 615 #pragma warning(push) |
578 #pragma warning(disable: 4018) | 616 #pragma warning(disable: 4018) |
579 #endif | 617 #endif |
580 » FD_SET(ctxt->fd, &rfd); | 618 |
| 619 FD_SET(ctxt->fd, &rfd); |
| 620 |
581 #ifdef _MSC_VER | 621 #ifdef _MSC_VER |
582 #pragma warning(pop) | 622 #pragma warning(pop) |
583 #endif | 623 #endif |
584 » | 624 |
585 » if ( (select(ctxt->fd+1, &rfd, NULL, NULL, &tv)<1) | 625 if ((select(ctxt->fd + 1, &rfd, NULL, NULL, &tv) < 1) |
586 #if defined(EINTR) | 626 #if defined(EINTR) |
587 » » && (errno != EINTR) | 627 && (errno != EINTR) |
588 #endif | 628 #endif |
589 » ) | 629 ) |
590 » » return(0); | 630 return (0); |
| 631 #endif /* !HAVE_POLL_H */ |
591 } | 632 } |
592 return(0); | 633 return (0); |
593 } | 634 } |
594 | 635 |
595 /** | 636 /** |
596 * xmlNanoHTTPReadLine: | 637 * xmlNanoHTTPReadLine: |
597 * @ctxt: an HTTP context | 638 * @ctxt: an HTTP context |
598 * | 639 * |
599 * Read one line in the HTTP server output, usually for extracting | 640 * Read one line in the HTTP server output, usually for extracting |
600 * the HTTP protocol informations from the answer header. | 641 * the HTTP protocol informations from the answer header. |
601 * | 642 * |
602 * Returns a newly allocated string with a copy of the line, or NULL | 643 * Returns a newly allocated string with a copy of the line, or NULL |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 if ((*cur != ' ') && (*cur != '\t')) return; | 720 if ((*cur != ' ') && (*cur != '\t')) return; |
680 while ((*cur == ' ') || (*cur == '\t')) cur++; | 721 while ((*cur == ' ') || (*cur == '\t')) cur++; |
681 if ((*cur < '0') || (*cur > '9')) return; | 722 if ((*cur < '0') || (*cur > '9')) return; |
682 while ((*cur >= '0') && (*cur <= '9')) { | 723 while ((*cur >= '0') && (*cur <= '9')) { |
683 ret *= 10; | 724 ret *= 10; |
684 ret += *cur - '0'; | 725 ret += *cur - '0'; |
685 cur++; | 726 cur++; |
686 } | 727 } |
687 if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return; | 728 if ((*cur != 0) && (*cur != ' ') && (*cur != '\t')) return; |
688 ctxt->returnValue = ret; | 729 ctxt->returnValue = ret; |
| 730 ctxt->version = version; |
689 } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) { | 731 } else if (!xmlStrncasecmp(BAD_CAST line, BAD_CAST"Content-Type:", 13)) { |
690 const xmlChar *charset, *last, *mime; | 732 const xmlChar *charset, *last, *mime; |
691 cur += 13; | 733 cur += 13; |
692 while ((*cur == ' ') || (*cur == '\t')) cur++; | 734 while ((*cur == ' ') || (*cur == '\t')) cur++; |
693 if (ctxt->contentType != NULL) | 735 if (ctxt->contentType != NULL) |
694 xmlFree(ctxt->contentType); | 736 xmlFree(ctxt->contentType); |
695 ctxt->contentType = xmlMemStrdup(cur); | 737 ctxt->contentType = xmlMemStrdup(cur); |
696 mime = (const xmlChar *) cur; | 738 mime = (const xmlChar *) cur; |
697 last = mime; | 739 last = mime; |
698 while ((*last != 0) && (*last != ' ') && (*last != '\t') && | 740 while ((*last != 0) && (*last != ' ') && (*last != '\t') && |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 * Attempt a connection to the given IP:port endpoint. It forces | 838 * Attempt a connection to the given IP:port endpoint. It forces |
797 * non-blocking semantic on the socket, and allow 60 seconds for | 839 * non-blocking semantic on the socket, and allow 60 seconds for |
798 * the host to answer. | 840 * the host to answer. |
799 * | 841 * |
800 * Returns -1 in case of failure, the file descriptor number otherwise | 842 * Returns -1 in case of failure, the file descriptor number otherwise |
801 */ | 843 */ |
802 | 844 |
803 static int | 845 static int |
804 xmlNanoHTTPConnectAttempt(struct sockaddr *addr) | 846 xmlNanoHTTPConnectAttempt(struct sockaddr *addr) |
805 { | 847 { |
| 848 #ifndef HAVE_POLL_H |
806 fd_set wfd; | 849 fd_set wfd; |
807 #ifdef _WINSOCKAPI_ | 850 #ifdef _WINSOCKAPI_ |
808 fd_set xfd; | 851 fd_set xfd; |
809 #endif | 852 #endif |
810 struct timeval tv; | 853 struct timeval tv; |
| 854 #else /* !HAVE_POLL_H */ |
| 855 struct pollfd p; |
| 856 #endif /* !HAVE_POLL_H */ |
811 int status; | 857 int status; |
| 858 |
812 int addrlen; | 859 int addrlen; |
| 860 |
813 SOCKET s; | 861 SOCKET s; |
814 | 862 |
815 #ifdef SUPPORT_IP6 | 863 #ifdef SUPPORT_IP6 |
816 if (addr->sa_family == AF_INET6) { | 864 if (addr->sa_family == AF_INET6) { |
817 » s = socket (PF_INET6, SOCK_STREAM, IPPROTO_TCP); | 865 s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); |
818 » addrlen = sizeof (struct sockaddr_in6); | 866 addrlen = sizeof(struct sockaddr_in6); |
819 } | 867 } else |
820 else | |
821 #endif | 868 #endif |
822 { | 869 { |
823 » s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); | 870 s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); |
824 » addrlen = sizeof (struct sockaddr_in); | 871 addrlen = sizeof(struct sockaddr_in); |
825 } | 872 } |
826 if (s==-1) { | 873 if (s == -1) { |
827 #ifdef DEBUG_HTTP | 874 #ifdef DEBUG_HTTP |
828 » perror("socket"); | 875 perror("socket"); |
829 #endif | 876 #endif |
830 » __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n"); | 877 __xmlIOErr(XML_FROM_HTTP, 0, "socket failed\n"); |
831 » return(-1); | 878 return (-1); |
832 } | 879 } |
833 | |
834 #ifdef _WINSOCKAPI_ | 880 #ifdef _WINSOCKAPI_ |
835 { | 881 { |
836 » u_long one = 1; | 882 u_long one = 1; |
837 | 883 |
838 » status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0; | 884 status = ioctlsocket(s, FIONBIO, &one) == SOCKET_ERROR ? -1 : 0; |
839 } | 885 } |
840 #else /* _WINSOCKAPI_ */ | 886 #else /* _WINSOCKAPI_ */ |
841 #if defined(VMS) | 887 #if defined(VMS) |
842 { | 888 { |
843 » int enable = 1; | 889 int enable = 1; |
844 » status = ioctl(s, FIONBIO, &enable); | 890 |
| 891 status = ioctl(s, FIONBIO, &enable); |
845 } | 892 } |
846 #else /* VMS */ | 893 #else /* VMS */ |
847 #if defined(__BEOS__) | 894 #if defined(__BEOS__) && !defined(__HAIKU__) |
848 » { | 895 { |
849 » » bool noblock = true; | 896 bool noblock = true; |
850 » » status = setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock, sizeof
(noblock)); | 897 |
851 » } | 898 status = |
| 899 setsockopt(s, SOL_SOCKET, SO_NONBLOCK, &noblock, |
| 900 sizeof(noblock)); |
| 901 } |
852 #else /* __BEOS__ */ | 902 #else /* __BEOS__ */ |
853 if ((status = fcntl(s, F_GETFL, 0)) != -1) { | 903 if ((status = fcntl(s, F_GETFL, 0)) != -1) { |
854 #ifdef O_NONBLOCK | 904 #ifdef O_NONBLOCK |
855 » status |= O_NONBLOCK; | 905 status |= O_NONBLOCK; |
856 #else /* O_NONBLOCK */ | 906 #else /* O_NONBLOCK */ |
857 #ifdef F_NDELAY | 907 #ifdef F_NDELAY |
858 » status |= F_NDELAY; | 908 status |= F_NDELAY; |
859 #endif /* F_NDELAY */ | 909 #endif /* F_NDELAY */ |
860 #endif /* !O_NONBLOCK */ | 910 #endif /* !O_NONBLOCK */ |
861 » status = fcntl(s, F_SETFL, status); | 911 status = fcntl(s, F_SETFL, status); |
862 } | 912 } |
863 if (status < 0) { | 913 if (status < 0) { |
864 #ifdef DEBUG_HTTP | 914 #ifdef DEBUG_HTTP |
865 » perror("nonblocking"); | 915 perror("nonblocking"); |
866 #endif | 916 #endif |
867 » __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n"); | 917 __xmlIOErr(XML_FROM_HTTP, 0, "error setting non-blocking IO\n"); |
868 » closesocket(s); | 918 closesocket(s); |
869 » return(-1); | 919 return (-1); |
870 } | 920 } |
871 #endif /* !__BEOS__ */ | 921 #endif /* !__BEOS__ */ |
872 #endif /* !VMS */ | 922 #endif /* !VMS */ |
873 #endif /* !_WINSOCKAPI_ */ | 923 #endif /* !_WINSOCKAPI_ */ |
874 | 924 |
875 if (connect (s, addr, addrlen) == -1) { | 925 if (connect(s, addr, addrlen) == -1) { |
876 » switch (socket_errno()) { | 926 switch (socket_errno()) { |
877 » case EINPROGRESS: | 927 case EINPROGRESS: |
878 » case EWOULDBLOCK: | 928 case EWOULDBLOCK: |
879 » » break; | 929 break; |
880 » default: | 930 default: |
881 » » __xmlIOErr(XML_FROM_HTTP, 0, "error connecting to HTTP server"); | 931 __xmlIOErr(XML_FROM_HTTP, 0, |
882 » » closesocket(s); | 932 "error connecting to HTTP server"); |
883 » » return(-1); | 933 closesocket(s); |
884 » } | 934 return (-1); |
885 }» | 935 } |
886 | 936 } |
| 937 #ifndef HAVE_POLL_H |
887 tv.tv_sec = timeout; | 938 tv.tv_sec = timeout; |
888 tv.tv_usec = 0; | 939 tv.tv_usec = 0; |
889 | 940 |
890 #ifdef _MSC_VER | 941 #ifdef _MSC_VER |
891 #pragma warning(push) | 942 #pragma warning(push) |
892 #pragma warning(disable: 4018) | 943 #pragma warning(disable: 4018) |
893 #endif | 944 #endif |
| 945 #ifndef _WINSOCKAPI_ |
| 946 if (s > FD_SETSIZE) |
| 947 return -1; |
| 948 #endif |
894 FD_ZERO(&wfd); | 949 FD_ZERO(&wfd); |
895 FD_SET(s, &wfd); | 950 FD_SET(s, &wfd); |
896 | 951 |
897 #ifdef _WINSOCKAPI_ | 952 #ifdef _WINSOCKAPI_ |
898 FD_ZERO(&xfd); | 953 FD_ZERO(&xfd); |
899 FD_SET(s, &xfd); | 954 FD_SET(s, &xfd); |
900 | 955 |
901 switch(select(s+1, NULL, &wfd, &xfd, &tv)) | 956 switch (select(s + 1, NULL, &wfd, &xfd, &tv)) |
902 #else | 957 #else |
903 switch(select(s+1, NULL, &wfd, NULL, &tv)) | 958 switch (select(s + 1, NULL, &wfd, NULL, &tv)) |
904 #endif | 959 #endif |
905 #ifdef _MSC_VER | 960 #ifdef _MSC_VER |
906 #pragma warning(pop) | 961 #pragma warning(pop) |
907 #endif | 962 #endif |
| 963 |
| 964 #else /* !HAVE_POLL_H */ |
| 965 p.fd = s; |
| 966 p.events = POLLOUT; |
| 967 switch (poll(&p, 1, timeout * 1000)) |
| 968 #endif /* !HAVE_POLL_H */ |
| 969 |
908 { | 970 { |
909 » case 0: | 971 case 0: |
910 » /* Time out */ | 972 /* Time out */ |
911 » __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out"); | 973 __xmlIOErr(XML_FROM_HTTP, 0, "Connect attempt timed out"); |
912 » closesocket(s); | 974 closesocket(s); |
913 » return(-1); | 975 return (-1); |
914 » case -1: | 976 case -1: |
915 » /* Ermm.. ?? */ | 977 /* Ermm.. ?? */ |
916 » __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed"); | 978 __xmlIOErr(XML_FROM_HTTP, 0, "Connect failed"); |
917 » closesocket(s); | 979 closesocket(s); |
918 » return(-1); | 980 return (-1); |
919 } | 981 } |
920 | 982 |
921 if ( FD_ISSET(s, &wfd) | 983 #ifndef HAVE_POLL_H |
| 984 if (FD_ISSET(s, &wfd) |
922 #ifdef _WINSOCKAPI_ | 985 #ifdef _WINSOCKAPI_ |
923 || FD_ISSET(s, &xfd) | 986 || FD_ISSET(s, &xfd) |
924 #endif | 987 #endif |
925 ) { | 988 ) |
926 » XML_SOCKLEN_T len; | 989 #else /* !HAVE_POLL_H */ |
927 » len = sizeof(status); | 990 if (p.revents == POLLOUT) |
| 991 #endif /* !HAVE_POLL_H */ |
| 992 { |
| 993 XML_SOCKLEN_T len; |
| 994 |
| 995 len = sizeof(status); |
928 #ifdef SO_ERROR | 996 #ifdef SO_ERROR |
929 » if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*)&status, &len) < 0 ) { | 997 if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char *) &status, &len) < |
930 » /* Solaris error code */ | 998 0) { |
931 » __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n"); | 999 /* Solaris error code */ |
932 » return (-1); | 1000 __xmlIOErr(XML_FROM_HTTP, 0, "getsockopt failed\n"); |
933 » } | 1001 return (-1); |
| 1002 } |
934 #endif | 1003 #endif |
935 » if ( status ) { | 1004 if (status) { |
936 » __xmlIOErr(XML_FROM_HTTP, 0, "Error connecting to remote host"); | 1005 __xmlIOErr(XML_FROM_HTTP, 0, |
937 » closesocket(s); | 1006 "Error connecting to remote host"); |
938 » errno = status; | 1007 closesocket(s); |
939 » return (-1); | 1008 errno = status; |
940 » } | 1009 return (-1); |
| 1010 } |
941 } else { | 1011 } else { |
942 » /* pbm */ | 1012 /* pbm */ |
943 » __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n"); | 1013 __xmlIOErr(XML_FROM_HTTP, 0, "select failed\n"); |
944 » closesocket(s); | 1014 closesocket(s); |
945 » return (-1); | 1015 return (-1); |
946 } | 1016 } |
947 | 1017 |
948 return(s); | 1018 return (s); |
949 } | 1019 } |
950 | 1020 |
951 /** | 1021 /** |
952 * xmlNanoHTTPConnectHost: | 1022 * xmlNanoHTTPConnectHost: |
953 * @host: the host name | 1023 * @host: the host name |
954 * @port: the port number | 1024 * @port: the port number |
955 * | 1025 * |
956 * Attempt a connection to the given host:port endpoint. It tries | 1026 * Attempt a connection to the given host:port endpoint. It tries |
957 * the multiple IP provided by the DNS if available. | 1027 * the multiple IP provided by the DNS if available. |
958 * | 1028 * |
959 * Returns -1 in case of failure, the file descriptor number otherwise | 1029 * Returns -1 in case of failure, the file descriptor number otherwise |
960 */ | 1030 */ |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1266 * The contentType, or redir, if provided must be freed by the caller | 1336 * The contentType, or redir, if provided must be freed by the caller |
1267 */ | 1337 */ |
1268 | 1338 |
1269 void* | 1339 void* |
1270 xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, | 1340 xmlNanoHTTPMethodRedir(const char *URL, const char *method, const char *input, |
1271 char **contentType, char **redir, | 1341 char **contentType, char **redir, |
1272 const char *headers, int ilen ) { | 1342 const char *headers, int ilen ) { |
1273 xmlNanoHTTPCtxtPtr ctxt; | 1343 xmlNanoHTTPCtxtPtr ctxt; |
1274 char *bp, *p; | 1344 char *bp, *p; |
1275 int blen, ret; | 1345 int blen, ret; |
1276 int head; | |
1277 int nbRedirects = 0; | 1346 int nbRedirects = 0; |
1278 char *redirURL = NULL; | 1347 char *redirURL = NULL; |
1279 #ifdef DEBUG_HTTP | 1348 #ifdef DEBUG_HTTP |
1280 int xmt_bytes; | 1349 int xmt_bytes; |
1281 #endif | 1350 #endif |
1282 | 1351 |
1283 if (URL == NULL) return(NULL); | 1352 if (URL == NULL) return(NULL); |
1284 if (method == NULL) method = "GET"; | 1353 if (method == NULL) method = "GET"; |
1285 xmlNanoHTTPInit(); | 1354 xmlNanoHTTPInit(); |
1286 | 1355 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1428 "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", | 1497 "xmlNanoHTTPMethodRedir: Only %d of %d %s %s\n", |
1429 xmt_bytes, ilen, | 1498 xmt_bytes, ilen, |
1430 "bytes of HTTP content sent to host", | 1499 "bytes of HTTP content sent to host", |
1431 ctxt->hostname ); | 1500 ctxt->hostname ); |
1432 #else | 1501 #else |
1433 xmlNanoHTTPSend( ctxt, input, ilen ); | 1502 xmlNanoHTTPSend( ctxt, input, ilen ); |
1434 #endif | 1503 #endif |
1435 } | 1504 } |
1436 | 1505 |
1437 ctxt->state = XML_NANO_HTTP_READ; | 1506 ctxt->state = XML_NANO_HTTP_READ; |
1438 head = 1; | |
1439 | 1507 |
1440 while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) { | 1508 while ((p = xmlNanoHTTPReadLine(ctxt)) != NULL) { |
1441 if (head && (*p == 0)) { | 1509 if (*p == 0) { |
1442 » head = 0; | |
1443 ctxt->content = ctxt->inrptr; | 1510 ctxt->content = ctxt->inrptr; |
1444 xmlFree(p); | 1511 xmlFree(p); |
1445 break; | 1512 break; |
1446 } | 1513 } |
1447 xmlNanoHTTPScanAnswer(ctxt, p); | 1514 xmlNanoHTTPScanAnswer(ctxt, p); |
1448 | 1515 |
1449 #ifdef DEBUG_HTTP | 1516 #ifdef DEBUG_HTTP |
1450 xmlGenericError(xmlGenericErrorContext, "<- %s\n", p); | 1517 xmlGenericError(xmlGenericErrorContext, "<- %s\n", p); |
1451 #endif | 1518 #endif |
1452 xmlFree(p); | 1519 xmlFree(p); |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1799 #include <stdio.h> | 1866 #include <stdio.h> |
1800 int main(int argc, char **argv) { | 1867 int main(int argc, char **argv) { |
1801 xmlGenericError(xmlGenericErrorContext, | 1868 xmlGenericError(xmlGenericErrorContext, |
1802 "%s : HTTP support not compiled in\n", argv[0]); | 1869 "%s : HTTP support not compiled in\n", argv[0]); |
1803 return(0); | 1870 return(0); |
1804 } | 1871 } |
1805 #endif /* STANDALONE */ | 1872 #endif /* STANDALONE */ |
1806 #endif /* LIBXML_HTTP_ENABLED */ | 1873 #endif /* LIBXML_HTTP_ENABLED */ |
1807 #define bottom_nanohttp | 1874 #define bottom_nanohttp |
1808 #include "elfgcchack.h" | 1875 #include "elfgcchack.h" |
OLD | NEW |