diff options
Diffstat (limited to 'src/microhttpd/response.c')
-rw-r--r-- | src/microhttpd/response.c | 239 |
1 files changed, 230 insertions, 9 deletions
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c index 3e967e68..f0ebf5c6 100644 --- a/src/microhttpd/response.c +++ b/src/microhttpd/response.c | |||
@@ -101,7 +101,8 @@ add_response_entry (struct MHD_Response *response, | |||
101 | */ | 101 | */ |
102 | int | 102 | int |
103 | MHD_add_response_header (struct MHD_Response *response, | 103 | MHD_add_response_header (struct MHD_Response *response, |
104 | const char *header, const char *content) | 104 | const char *header, |
105 | const char *content) | ||
105 | { | 106 | { |
106 | return add_response_entry (response, | 107 | return add_response_entry (response, |
107 | MHD_HEADER_KIND, | 108 | MHD_HEADER_KIND, |
@@ -121,7 +122,8 @@ MHD_add_response_header (struct MHD_Response *response, | |||
121 | */ | 122 | */ |
122 | int | 123 | int |
123 | MHD_add_response_footer (struct MHD_Response *response, | 124 | MHD_add_response_footer (struct MHD_Response *response, |
124 | const char *footer, const char *content) | 125 | const char *footer, |
126 | const char *content) | ||
125 | { | 127 | { |
126 | return add_response_entry (response, | 128 | return add_response_entry (response, |
127 | MHD_FOOTER_KIND, | 129 | MHD_FOOTER_KIND, |
@@ -184,7 +186,8 @@ MHD_del_response_header (struct MHD_Response *response, | |||
184 | */ | 186 | */ |
185 | int | 187 | int |
186 | MHD_get_response_headers (struct MHD_Response *response, | 188 | MHD_get_response_headers (struct MHD_Response *response, |
187 | MHD_KeyValueIterator iterator, void *iterator_cls) | 189 | MHD_KeyValueIterator iterator, |
190 | void *iterator_cls) | ||
188 | { | 191 | { |
189 | struct MHD_HTTP_Header *pos; | 192 | struct MHD_HTTP_Header *pos; |
190 | int numHeaders = 0; | 193 | int numHeaders = 0; |
@@ -316,7 +319,10 @@ MHD_set_response_options (struct MHD_Response *response, | |||
316 | * @return number of bytes written | 319 | * @return number of bytes written |
317 | */ | 320 | */ |
318 | static ssize_t | 321 | static ssize_t |
319 | file_reader (void *cls, uint64_t pos, char *buf, size_t max) | 322 | file_reader (void *cls, |
323 | uint64_t pos, | ||
324 | char *buf, | ||
325 | size_t max) | ||
320 | { | 326 | { |
321 | struct MHD_Response *response = cls; | 327 | struct MHD_Response *response = cls; |
322 | ssize_t n; | 328 | ssize_t n; |
@@ -397,7 +403,9 @@ MHD_create_response_from_fd_at_offset (size_t size, | |||
397 | int fd, | 403 | int fd, |
398 | off_t offset) | 404 | off_t offset) |
399 | { | 405 | { |
400 | return MHD_create_response_from_fd_at_offset64 (size, fd, offset); | 406 | return MHD_create_response_from_fd_at_offset64 (size, |
407 | fd, | ||
408 | offset); | ||
401 | } | 409 | } |
402 | 410 | ||
403 | 411 | ||
@@ -461,7 +469,9 @@ struct MHD_Response * | |||
461 | MHD_create_response_from_fd (size_t size, | 469 | MHD_create_response_from_fd (size_t size, |
462 | int fd) | 470 | int fd) |
463 | { | 471 | { |
464 | return MHD_create_response_from_fd_at_offset64 (size, fd, 0); | 472 | return MHD_create_response_from_fd_at_offset64 (size, |
473 | fd, | ||
474 | 0); | ||
465 | } | 475 | } |
466 | 476 | ||
467 | 477 | ||
@@ -482,7 +492,9 @@ _MHD_EXTERN struct MHD_Response * | |||
482 | MHD_create_response_from_fd64 (uint64_t size, | 492 | MHD_create_response_from_fd64 (uint64_t size, |
483 | int fd) | 493 | int fd) |
484 | { | 494 | { |
485 | return MHD_create_response_from_fd_at_offset64 (size, fd, 0); | 495 | return MHD_create_response_from_fd_at_offset64 (size, |
496 | fd, | ||
497 | 0); | ||
486 | } | 498 | } |
487 | 499 | ||
488 | 500 | ||
@@ -502,7 +514,9 @@ MHD_create_response_from_fd64 (uint64_t size, | |||
502 | */ | 514 | */ |
503 | struct MHD_Response * | 515 | struct MHD_Response * |
504 | MHD_create_response_from_data (size_t size, | 516 | MHD_create_response_from_data (size_t size, |
505 | void *data, int must_free, int must_copy) | 517 | void *data, |
518 | int must_free, | ||
519 | int must_copy) | ||
506 | { | 520 | { |
507 | struct MHD_Response *response; | 521 | struct MHD_Response *response; |
508 | void *tmp; | 522 | void *tmp; |
@@ -513,7 +527,7 @@ MHD_create_response_from_data (size_t size, | |||
513 | return NULL; | 527 | return NULL; |
514 | memset (response, 0, sizeof (struct MHD_Response)); | 528 | memset (response, 0, sizeof (struct MHD_Response)); |
515 | response->fd = -1; | 529 | response->fd = -1; |
516 | if (!MHD_mutex_init_ (&response->mutex)) | 530 | if (! MHD_mutex_init_ (&response->mutex)) |
517 | { | 531 | { |
518 | free (response); | 532 | free (response); |
519 | return NULL; | 533 | return NULL; |
@@ -563,6 +577,208 @@ MHD_create_response_from_buffer (size_t size, | |||
563 | } | 577 | } |
564 | 578 | ||
565 | 579 | ||
580 | #if 0 | ||
581 | /** | ||
582 | * Handle given to the application to manage special | ||
583 | * actions relating to MHD responses that "upgrade" | ||
584 | * the HTTP protocol (i.e. to WebSockets). | ||
585 | */ | ||
586 | struct MHD_UpgradeResponseHandle | ||
587 | { | ||
588 | |||
589 | /** | ||
590 | * The connection for which this is an upgrade handle. Note that | ||
591 | * because a response may be shared over many connections, this may | ||
592 | * not be the only upgrade handle for the response of this connection. | ||
593 | */ | ||
594 | struct MHD_Connection *connection; | ||
595 | |||
596 | /** | ||
597 | * The socket we gave to the application (r/w). | ||
598 | */ | ||
599 | MHD_SOCKET app_sock; | ||
600 | |||
601 | /** | ||
602 | * If @a app_sock was a socketpair, our end of it, otherwise | ||
603 | * #MHD_INVALID_SOCKET; (r/w). | ||
604 | */ | ||
605 | MHD_SOCKET mhd_sock; | ||
606 | |||
607 | }; | ||
608 | |||
609 | |||
610 | /** | ||
611 | * This connection-specific callback is provided by MHD to | ||
612 | * applications (unusual) during the #MHD_UpgradeHandler. | ||
613 | * It allows applications to perform 'special' actions on | ||
614 | * the underlying socket from the upgrade. | ||
615 | * | ||
616 | * @param urh the handle identifying the connection to perform | ||
617 | * the upgrade @a action on. | ||
618 | * @param action which action should be performed | ||
619 | * @param ... arguments to the action (depends on the action) | ||
620 | * @return #MHD_NO on error, #MHD_YES on success | ||
621 | */ | ||
622 | _MHD_EXTERN int | ||
623 | MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh, | ||
624 | enum MHD_UpgradeAction action, | ||
625 | ...) | ||
626 | { | ||
627 | switch (action) | ||
628 | { | ||
629 | case MHD_UPGRADE_ACTION_CLOSE: | ||
630 | /* Application is done with this connection, tear it down! */ | ||
631 | if ( (MHD_INVALID_SOCKET != urh->app_socket) && | ||
632 | (0 != MHD_socket_close (urh->app_socket)) ) | ||
633 | MHD_PANIC ("close failed\n"); | ||
634 | if ( (MHD_INVALID_SOCKET != urh->mhd_socket) && | ||
635 | (0 != MHD_socket_close (urh->mhd_socket)) ) | ||
636 | MHD_PANIC ("close failed\n"); | ||
637 | MHD_connection_resume (urh->connection); | ||
638 | MHD_connection_close_ (urh->connection, | ||
639 | MHD_REQUEST_TERMINATED_COMPLETED_OK); | ||
640 | free (urh); | ||
641 | return MHD_YES; | ||
642 | case MHD_UPGRADE_ACTION_CORK: | ||
643 | /* FIXME: not implemented */ | ||
644 | return MHD_NO; | ||
645 | default: | ||
646 | /* we don't understand this one */ | ||
647 | return MHD_NO; | ||
648 | } | ||
649 | } | ||
650 | |||
651 | |||
652 | /** | ||
653 | * We are done sending the header of a given response | ||
654 | * to the client. Now it is time to perform the upgrade | ||
655 | * and hand over the connection to the application. | ||
656 | * | ||
657 | * @param response the response that was created for an upgrade | ||
658 | * @param connection the specific connection we are upgrading | ||
659 | * @return #MHD_YES on success, #MHD_NO on failure (will cause | ||
660 | * connection to be closed) | ||
661 | */ | ||
662 | // FIXME: This function will need to be called at the right place(s) | ||
663 | // in the connection processing (just after we are done sending the header) | ||
664 | // (for responses that have the 'upgrade_header' callback set). | ||
665 | int | ||
666 | MHD_response_execute_upgrade_ (struct MHD_Response *response, | ||
667 | struct MHD_Connection *connection) | ||
668 | { | ||
669 | struct MHD_UpgradeResponseHandle *urh; | ||
670 | int sv[2]; | ||
671 | size_t rbo; | ||
672 | |||
673 | urh = malloc (sizeof (struct MHD_UpgradeResponseHandle)); | ||
674 | if (NULL == urh) | ||
675 | return MHD_NO; | ||
676 | #if HTTPS_SUPPORT | ||
677 | if (0 != (connection->daemon->flags & MHD_USE_SSL) ) | ||
678 | { | ||
679 | /* FIXME: this is non-portable for now; W32 port pending... */ | ||
680 | if (0 != socketpair (AF_UNIX, | ||
681 | SOCK_STREAM, | ||
682 | 0, | ||
683 | sv)) | ||
684 | { | ||
685 | free (urh); | ||
686 | return MHD_NO; | ||
687 | } | ||
688 | urh->app_socket = sv[0]; | ||
689 | urh->mhd_socket = sv[1]; | ||
690 | urh->connection = connection; | ||
691 | rbo = connection->read_buffer_offset; | ||
692 | connection->read_buffer_offset = 0; | ||
693 | response->upgrade_handler (response->upgrade_handler_cls, | ||
694 | connection, | ||
695 | connection->read_buffer, | ||
696 | rbo, | ||
697 | urh->app_sock, | ||
698 | urh); | ||
699 | /* As far as MHD is concerned, this connection is | ||
700 | suspended; it will be resumed once we are done | ||
701 | in the #MHD_upgrade_action() function */ | ||
702 | MHD_connection_suspend (connection); | ||
703 | /* FIXME: also need to start some processing logic in _all_ MHD | ||
704 | event loops for the sv traffic! (NOT IMPLEMENTED!!!) */ | ||
705 | return MHD_YES; | ||
706 | } | ||
707 | #endif | ||
708 | urh->app_socket = MHD_INVALID_SOCKET; | ||
709 | urh->mhd_socket = MHD_INVALID_SOCKET; | ||
710 | rbo = connection->read_buffer_offset; | ||
711 | connection->read_buffer_offset = 0; | ||
712 | response->upgrade_handler (response->upgrade_handler_cls, | ||
713 | connection, | ||
714 | connection->read_buffer, | ||
715 | rbo, | ||
716 | connection->socket_fd, | ||
717 | urh); | ||
718 | /* As far as MHD is concerned, this connection is | ||
719 | suspended; it will be resumed once we are done | ||
720 | in the #MHD_upgrade_action() function */ | ||
721 | MHD_connection_suspend (connection); | ||
722 | return MHD_YES; | ||
723 | } | ||
724 | |||
725 | |||
726 | /** | ||
727 | * Create a response object that can be used for 101 UPGRADE | ||
728 | * responses, for example to implement WebSockets. After sending the | ||
729 | * response, control over the data stream is given to the callback (which | ||
730 | * can then, for example, start some bi-directional communication). | ||
731 | * If the response is queued for multiple connections, the callback | ||
732 | * will be called for each connection. The callback | ||
733 | * will ONLY be called after the response header was successfully passed | ||
734 | * to the OS; if there are communication errors before, the usual MHD | ||
735 | * connection error handling code will be performed. | ||
736 | * | ||
737 | * Setting the correct HTTP code (i.e. MHD_HTTP_SWITCHING_PROTOCOLS) | ||
738 | * and setting correct HTTP headers for the upgrade must be done | ||
739 | * manually (this way, it is possible to implement most existing | ||
740 | * WebSocket versions using this API; in fact, this API might be useful | ||
741 | * for any protocol switch, not just WebSockets). Note that | ||
742 | * draft-ietf-hybi-thewebsocketprotocol-00 cannot be implemented this | ||
743 | * way as the header "HTTP/1.1 101 WebSocket Protocol Handshake" | ||
744 | * cannot be generated; instead, MHD will always produce "HTTP/1.1 101 | ||
745 | * Switching Protocols" (if the response code 101 is used). | ||
746 | * | ||
747 | * As usual, the response object can be extended with header | ||
748 | * information and then be used any number of times (as long as the | ||
749 | * header information is not connection-specific). | ||
750 | * | ||
751 | * @param upgrade_handler function to call with the 'upgraded' socket | ||
752 | * @param upgrade_handler_cls closure for @a upgrade_handler | ||
753 | * @return NULL on error (i.e. invalid arguments, out of memory) | ||
754 | */ | ||
755 | _MHD_EXTERN struct MHD_Response * | ||
756 | MHD_create_response_for_upgrade (MHD_UpgradeHandler upgrade_handler, | ||
757 | void *upgrade_handler_cls) | ||
758 | { | ||
759 | struct MHD_Response *response; | ||
760 | |||
761 | if (NULL == upgrade_header) | ||
762 | return NULL; /* invalid request */ | ||
763 | response = malloc (sizeof (struct MHD_Response)); | ||
764 | if (NULL == response) | ||
765 | return NULL; | ||
766 | memset (response, 0, sizeof (struct MHD_Response)); | ||
767 | if (! MHD_mutex_init_ (&response->mutex)) | ||
768 | { | ||
769 | free (response); | ||
770 | return NULL; | ||
771 | } | ||
772 | urh->response = response; | ||
773 | response->upgrade_handler = upgrade_handler; | ||
774 | response->upgrade_handler_cls = upgrade_handler_cls; | ||
775 | response->total_size = MHD_SIZE_UNKNOWN; | ||
776 | response->reference_count = 1; | ||
777 | return response; | ||
778 | } | ||
779 | #endif | ||
780 | |||
781 | |||
566 | /** | 782 | /** |
567 | * Destroy a response object and associated resources. Note that | 783 | * Destroy a response object and associated resources. Note that |
568 | * libmicrohttpd may keep some of the resources around if the response | 784 | * libmicrohttpd may keep some of the resources around if the response |
@@ -601,6 +817,11 @@ MHD_destroy_response (struct MHD_Response *response) | |||
601 | } | 817 | } |
602 | 818 | ||
603 | 819 | ||
820 | /** | ||
821 | * Increments the reference counter for the @a response. | ||
822 | * | ||
823 | * @param response object to modify | ||
824 | */ | ||
604 | void | 825 | void |
605 | MHD_increment_response_rc (struct MHD_Response *response) | 826 | MHD_increment_response_rc (struct MHD_Response *response) |
606 | { | 827 | { |