aboutsummaryrefslogtreecommitdiff
path: root/src/daemon/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon/connection.c')
-rw-r--r--src/daemon/connection.c299
1 files changed, 79 insertions, 220 deletions
diff --git a/src/daemon/connection.c b/src/daemon/connection.c
index eef9e9e8..476d1c89 100644
--- a/src/daemon/connection.c
+++ b/src/daemon/connection.c
@@ -57,7 +57,7 @@
57/** 57/**
58 * Add extra debug messages with reasons for closing connections 58 * Add extra debug messages with reasons for closing connections
59 * (non-error reasons). 59 * (non-error reasons).
60 */ 60 */
61#define DEBUG_CLOSE 0 61#define DEBUG_CLOSE 0
62 62
63 63
@@ -184,17 +184,17 @@ MHD_need_100_continue (struct MHD_Connection *connection)
184 * A serious error occured, close the 184 * A serious error occured, close the
185 * connection (and notify the application). 185 * connection (and notify the application).
186 */ 186 */
187static void 187static void
188connection_close_error(struct MHD_Connection * connection) 188connection_close_error (struct MHD_Connection *connection)
189{ 189{
190 SHUTDOWN (connection->socket_fd, SHUT_RDWR); 190 SHUTDOWN (connection->socket_fd, SHUT_RDWR);
191 CLOSE (connection->socket_fd); 191 CLOSE (connection->socket_fd);
192 connection->socket_fd = -1; 192 connection->socket_fd = -1;
193 if (connection->daemon->notify_completed != NULL) 193 if (connection->daemon->notify_completed != NULL)
194 connection->daemon->notify_completed(connection->daemon->notify_completed_cls, 194 connection->daemon->notify_completed (connection->daemon->
195 connection, 195 notify_completed_cls, connection,
196 &connection->client_context, 196 &connection->client_context,
197 MHD_REQUEST_TERMINATED_WITH_ERROR); 197 MHD_REQUEST_TERMINATED_WITH_ERROR);
198} 198}
199 199
200/** 200/**
@@ -222,11 +222,10 @@ ready_response (struct MHD_Connection *connection)
222 { 222 {
223 /* end of message, signal other side by closing! */ 223 /* end of message, signal other side by closing! */
224#if DEBUG_CLOSE 224#if DEBUG_CLOSE
225 MHD_DLOG (connection->daemon, 225 MHD_DLOG (connection->daemon, "Closing connection (end of response)\n");
226 "Closing connection (end of response)\n");
227#endif 226#endif
228 response->total_size = connection->messagePos; 227 response->total_size = connection->messagePos;
229 connection_close_error(connection); 228 connection_close_error (connection);
230 return MHD_NO; 229 return MHD_NO;
231 } 230 }
232 response->data_start = connection->messagePos; 231 response->data_start = connection->messagePos;
@@ -281,7 +280,6 @@ MHD_connection_get_fdset (struct MHD_Connection *connection,
281 { 280 {
282 if ((connection->read_close == MHD_NO) && 281 if ((connection->read_close == MHD_NO) &&
283 ((connection->headersReceived == 1) && 282 ((connection->headersReceived == 1) &&
284 (connection->post_processed == MHD_NO) &&
285 (connection->readLoc == connection->read_buffer_size))) 283 (connection->readLoc == connection->read_buffer_size)))
286 { 284 {
287 /* try growing the read buffer, just in case */ 285 /* try growing the read buffer, just in case */
@@ -297,7 +295,7 @@ MHD_connection_get_fdset (struct MHD_Connection *connection,
297 connection->read_buffer_size = 295 connection->read_buffer_size =
298 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE; 296 connection->read_buffer_size * 2 + MHD_BUF_INC_SIZE;
299 FD_SET (fd, read_fd_set); 297 FD_SET (fd, read_fd_set);
300 if (fd > *max_fd) 298 if (fd > *max_fd)
301 *max_fd = fd; 299 *max_fd = fd;
302 } 300 }
303 } 301 }
@@ -430,29 +428,6 @@ MHD_connection_add_header (struct MHD_Connection *connection,
430} 428}
431 429
432/** 430/**
433 * Process escape sequences ('+'=space, %HH)
434 */
435static void
436MHD_http_unescape (char *val)
437{
438 char *esc;
439 unsigned int num;
440
441 while (NULL != (esc = strstr (val, "+")))
442 *esc = ' ';
443 while (NULL != (esc = strstr (val, "%")))
444 {
445 if ((1 == sscanf (&esc[1],
446 "%2x", &num)) || (1 == sscanf (&esc[1], "%2X", &num)))
447 {
448 esc[0] = (unsigned char) num;
449 memmove (&esc[1], &esc[3], strlen (&esc[3]));
450 }
451 val = esc + 1;
452 }
453}
454
455/**
456 * @return MHD_NO on failure (out of memory), MHD_YES for success 431 * @return MHD_NO on failure (out of memory), MHD_YES for success
457 */ 432 */
458static int 433static int
@@ -615,10 +590,11 @@ MHD_parse_connection_headers (struct MHD_Connection *connection)
615 const char *clen; 590 const char *clen;
616 const char *end; 591 const char *end;
617 unsigned long long cval; 592 unsigned long long cval;
618 struct MHD_Response * response; 593 struct MHD_Response *response;
619 594
620 if (connection->bodyReceived == 1) 595 if (connection->bodyReceived == 1)
621 abort (); 596 abort ();
597 colon = NULL; /* make gcc happy */
622 last = NULL; 598 last = NULL;
623 while (NULL != (line = MHD_get_next_header_line (connection))) 599 while (NULL != (line = MHD_get_next_header_line (connection)))
624 { 600 {
@@ -707,29 +683,28 @@ MHD_parse_connection_headers (struct MHD_Connection *connection)
707 this request */ 683 this request */
708 connection->read_close = MHD_YES; 684 connection->read_close = MHD_YES;
709 } 685 }
710 686
711 if ( (0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options)) && 687 if ((0 != (MHD_USE_PEDANTIC_CHECKS & connection->daemon->options))
712 (NULL != connection->version) && 688 && (NULL != connection->version)
713 (0 == strcasecmp(MHD_HTTP_VERSION_1_1, 689 && (0 == strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))
714 connection->version)) && 690 && (NULL ==
715 (NULL == MHD_lookup_connection_value(connection, 691 MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
716 MHD_HEADER_KIND, 692 MHD_HTTP_HEADER_HOST)))
717 MHD_HTTP_HEADER_HOST)) ) { 693 {
718 /* die, http 1.1 request without host and we are pedantic */ 694 /* die, http 1.1 request without host and we are pedantic */
719 connection->bodyReceived = MHD_YES; 695 connection->bodyReceived = MHD_YES;
720 connection->read_close = MHD_YES; 696 connection->read_close = MHD_YES;
721 MHD_DLOG (connection->daemon, 697 MHD_DLOG (connection->daemon,
722 "Received `%s' request without `%s' header.\n", 698 "Received `%s' request without `%s' header.\n",
723 MHD_HTTP_VERSION_1_1, 699 MHD_HTTP_VERSION_1_1, MHD_HTTP_HEADER_HOST);
724 MHD_HTTP_HEADER_HOST); 700 response =
725 response = MHD_create_response_from_data (strlen (REQUEST_LACKS_HOST), 701 MHD_create_response_from_data (strlen (REQUEST_LACKS_HOST),
726 REQUEST_LACKS_HOST, MHD_NO, MHD_NO); 702 REQUEST_LACKS_HOST, MHD_NO,
727 MHD_queue_response (connection, 703 MHD_NO);
728 MHD_HTTP_BAD_REQUEST, 704 MHD_queue_response (connection, MHD_HTTP_BAD_REQUEST, response);
729 response); 705 MHD_destroy_response (response);
730 MHD_destroy_response (response); 706 }
731 } 707
732
733 break; 708 break;
734 } 709 }
735 /* line should be normal header line, find colon */ 710 /* line should be normal header line, find colon */
@@ -761,8 +736,8 @@ MHD_parse_connection_headers (struct MHD_Connection *connection)
761 return; 736 return;
762DIE: 737DIE:
763 MHD_DLOG (connection->daemon, 738 MHD_DLOG (connection->daemon,
764 "Closing connection (problem parsing headers)\n"); 739 "Closing connection (problem parsing headers)\n");
765 connection_close_error(connection); 740 connection_close_error (connection);
766} 741}
767 742
768 743
@@ -784,107 +759,6 @@ MHD_find_access_handler (struct MHD_Connection *connection)
784 return &connection->daemon->default_handler; 759 return &connection->daemon->default_handler;
785} 760}
786 761
787/**
788 * Test if we are able to process the POST data.
789 * This depends on available memory (enough to load
790 * all of the POST data into the pool) and the
791 * content encoding of the POST data. And of course,
792 * this requires that the request is actually a
793 * POST request.
794 *
795 * @return MHD_YES if so
796 */
797static int
798MHD_test_post_data (struct MHD_Connection *connection)
799{
800 const char *encoding;
801 void *buf;
802
803 if ((connection->method == NULL) ||
804 (connection->response != NULL) ||
805 (0 != strcasecmp (connection->method, MHD_HTTP_METHOD_POST)))
806 return MHD_NO;
807 encoding = MHD_lookup_connection_value (connection,
808 MHD_HEADER_KIND,
809 MHD_HTTP_HEADER_CONTENT_TYPE);
810 if (encoding == NULL)
811 return MHD_NO;
812 if ((0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED,
813 encoding)) && (connection->uploadSize != -1))
814 {
815 buf = MHD_pool_reallocate (connection->pool,
816 connection->read_buffer,
817 (connection->read_buffer == NULL) ? 0 : connection->read_buffer_size + 1,
818 connection->uploadSize + 1);
819 if (buf == NULL)
820 return MHD_NO;
821 connection->read_buffer_size = connection->uploadSize;
822 connection->read_buffer = buf;
823 return MHD_YES;
824 }
825 return MHD_NO;
826}
827
828/**
829 * Process the POST data here (adding to headers).
830 *
831 * Needs to first check POST encoding and then do
832 * the right thing (TM). The POST data is in the
833 * connection's post_data buffer between the postPos
834 * and postLoc offsets. The POST message maybe
835 * incomplete. The existing buffer (allocated from
836 * the pool) can be used and modified but must then
837 * be properly removed from the struct.
838 *
839 * @return MHD_YES on success, MHD_NO on error (i.e. out of
840 * memory).
841 */
842static int
843MHD_parse_post_data (struct MHD_Connection *connection)
844{
845 const char *encoding;
846 int ret;
847
848 encoding = MHD_lookup_connection_value (connection,
849 MHD_HEADER_KIND,
850 MHD_HTTP_HEADER_CONTENT_TYPE);
851 if (encoding == NULL)
852 return MHD_NO;
853 if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_FORM_URLENCODED, encoding))
854 {
855 /* add 0-termination, that's why the actual buffer size
856 is always 1 more than what is actually required for the data! */
857 connection->read_buffer[connection->readLoc] = '\0';
858 ret = parse_arguments (MHD_POSTDATA_KIND,
859 connection, connection->read_buffer);
860 /* invalidate read buffer for other uses --
861 in particular, do not give it to the
862 client; if this were to be needed, we would
863 have to make a copy, which would double memory
864 requirements */
865 connection->read_buffer_size = 0;
866 connection->readLoc = 0;
867 connection->uploadSize = 0;
868 connection->read_buffer = NULL;
869 return ret;
870 }
871 if (0 == strcasecmp (MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA, encoding))
872 {
873 /* this code should never been reached right now,
874 since the test_post_data function would already
875 return MHD_NO; code is here only for future
876 extensions... */
877 /* see http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 */
878 MHD_DLOG (connection->daemon,
879 "Unsupported multipart encoding of POST data specified, not processing POST data.\n");
880 return MHD_NO;
881 }
882 /* this should never be reached, just here for
883 error checking */
884 MHD_DLOG (connection->daemon,
885 "Unknown encoding of POST data specified, not processing POST data.\n");
886 return MHD_NO;
887}
888 762
889/** 763/**
890 * Call the handler of the application for this 764 * Call the handler of the application for this
@@ -908,12 +782,12 @@ MHD_call_connection_handler (struct MHD_Connection *connection)
908 connection->method, 782 connection->method,
909 connection->version, 783 connection->version,
910 connection->read_buffer, &processed, 784 connection->read_buffer, &processed,
911 &connection->client_context)) 785 &connection->client_context))
912 { 786 {
913 /* serios internal error, close connection */ 787 /* serios internal error, close connection */
914 MHD_DLOG (connection->daemon, 788 MHD_DLOG (connection->daemon,
915 "Internal application error, closing connection.\n"); 789 "Internal application error, closing connection.\n");
916 connection_close_error(connection); 790 connection_close_error (connection);
917 return; 791 return;
918 } 792 }
919 /* dh left "processed" bytes in buffer for next time... */ 793 /* dh left "processed" bytes in buffer for next time... */
@@ -929,10 +803,11 @@ MHD_call_connection_handler (struct MHD_Connection *connection)
929 { 803 {
930 connection->bodyReceived = 1; 804 connection->bodyReceived = 1;
931 if (connection->read_buffer != NULL) 805 if (connection->read_buffer != NULL)
932 MHD_pool_reallocate(connection->pool, 806 MHD_pool_reallocate (connection->pool,
933 connection->read_buffer, 807 connection->read_buffer,
934 (connection->read_buffer == NULL) ? 0 : connection->read_buffer_size + 1, 808 (connection->read_buffer ==
935 0); 809 NULL) ? 0 : connection->read_buffer_size + 1,
810 0);
936 connection->readLoc = 0; 811 connection->readLoc = 0;
937 connection->read_buffer_size = 0; 812 connection->read_buffer_size = 0;
938 connection->read_buffer = NULL; 813 connection->read_buffer = NULL;
@@ -957,7 +832,7 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
957 if (connection->pool == NULL) 832 if (connection->pool == NULL)
958 { 833 {
959 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n"); 834 MHD_DLOG (connection->daemon, "Failed to create memory pool!\n");
960 connection_close_error(connection); 835 connection_close_error (connection);
961 return MHD_NO; 836 return MHD_NO;
962 } 837 }
963 if ((connection->readLoc >= connection->read_buffer_size) && 838 if ((connection->readLoc >= connection->read_buffer_size) &&
@@ -995,15 +870,14 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
995 return MHD_NO; 870 return MHD_NO;
996 MHD_DLOG (connection->daemon, 871 MHD_DLOG (connection->daemon,
997 "Failed to receive data: %s\n", STRERROR (errno)); 872 "Failed to receive data: %s\n", STRERROR (errno));
998 connection_close_error(connection); 873 connection_close_error (connection);
999 return MHD_YES; 874 return MHD_YES;
1000 } 875 }
1001 if (bytes_read == 0) 876 if (bytes_read == 0)
1002 { 877 {
1003 /* other side closed connection */ 878 /* other side closed connection */
1004 connection->read_close = MHD_YES; 879 connection->read_close = MHD_YES;
1005 if ( (connection->headersReceived == 1) && 880 if ((connection->headersReceived == 1) && (connection->readLoc > 0))
1006 (connection->readLoc > 0) )
1007 MHD_call_connection_handler (connection); 881 MHD_call_connection_handler (connection);
1008#if DEBUG_CLOSE 882#if DEBUG_CLOSE
1009 MHD_DLOG (connection->daemon, 883 MHD_DLOG (connection->daemon,
@@ -1014,24 +888,9 @@ MHD_connection_handle_read (struct MHD_Connection *connection)
1014 } 888 }
1015 connection->readLoc += bytes_read; 889 connection->readLoc += bytes_read;
1016 if (connection->headersReceived == 0) 890 if (connection->headersReceived == 0)
1017 { 891 MHD_parse_connection_headers (connection);
1018 MHD_parse_connection_headers (connection); 892 if ((connection->headersReceived == 1) && (connection->method != NULL))
1019 if (connection->headersReceived == 1) 893 MHD_call_connection_handler (connection);
1020 {
1021 connection->post_processed = MHD_test_post_data (connection);
1022 }
1023 }
1024 if (connection->headersReceived == 1)
1025 {
1026 if ((connection->post_processed == MHD_YES) &&
1027 (connection->uploadSize == connection->readLoc))
1028 if (MHD_NO == MHD_parse_post_data (connection))
1029 connection->post_processed = MHD_NO;
1030 if (((connection->post_processed == MHD_NO) ||
1031 (connection->read_buffer_size == connection->readLoc)) &&
1032 (connection->method != NULL))
1033 MHD_call_connection_handler (connection);
1034 }
1035 return MHD_YES; 894 return MHD_YES;
1036} 895}
1037 896
@@ -1171,14 +1030,13 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1171 return MHD_YES; 1030 return MHD_YES;
1172 MHD_DLOG (connection->daemon, 1031 MHD_DLOG (connection->daemon,
1173 "Failed to send data: %s\n", STRERROR (errno)); 1032 "Failed to send data: %s\n", STRERROR (errno));
1174 connection_close_error(connection); 1033 connection_close_error (connection);
1175 return MHD_YES; 1034 return MHD_YES;
1176 } 1035 }
1177#if DEBUG_SEND_DATA 1036#if DEBUG_SEND_DATA
1178 fprintf(stderr, 1037 fprintf (stderr,
1179 "Sent 100 continue response: `%.*s'\n", 1038 "Sent 100 continue response: `%.*s'\n",
1180 ret, 1039 ret, &HTTP_100_CONTINUE[connection->continuePos]);
1181 &HTTP_100_CONTINUE[connection->continuePos]);
1182#endif 1040#endif
1183 connection->continuePos += ret; 1041 connection->continuePos += ret;
1184 return MHD_YES; 1042 return MHD_YES;
@@ -1195,9 +1053,9 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1195 (MHD_NO == MHD_build_header_response (connection))) 1053 (MHD_NO == MHD_build_header_response (connection)))
1196 { 1054 {
1197 /* oops - close! */ 1055 /* oops - close! */
1198 MHD_DLOG (connection->daemon, 1056 MHD_DLOG (connection->daemon,
1199 "Closing connection (failed to create response header)\n"); 1057 "Closing connection (failed to create response header)\n");
1200 connection_close_error(connection); 1058 connection_close_error (connection);
1201 return MHD_NO; 1059 return MHD_NO;
1202 } 1060 }
1203 ret = SEND (connection->socket_fd, 1061 ret = SEND (connection->socket_fd,
@@ -1209,14 +1067,13 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1209 return MHD_YES; 1067 return MHD_YES;
1210 MHD_DLOG (connection->daemon, 1068 MHD_DLOG (connection->daemon,
1211 "Failed to send data: %s\n", STRERROR (errno)); 1069 "Failed to send data: %s\n", STRERROR (errno));
1212 connection_close_error(connection); 1070 connection_close_error (connection);
1213 return MHD_YES; 1071 return MHD_YES;
1214 } 1072 }
1215#if DEBUG_SEND_DATA 1073#if DEBUG_SEND_DATA
1216 fprintf(stderr, 1074 fprintf (stderr,
1217 "Sent HEADER response: `%.*s'\n", 1075 "Sent HEADER response: `%.*s'\n",
1218 ret, 1076 ret, &connection->write_buffer[connection->writePos]);
1219 &connection->write_buffer[connection->writePos]);
1220#endif 1077#endif
1221 connection->writePos += ret; 1078 connection->writePos += ret;
1222 if (connection->writeLoc == connection->writePos) 1079 if (connection->writeLoc == connection->writePos)
@@ -1259,14 +1116,14 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1259 return MHD_YES; 1116 return MHD_YES;
1260 MHD_DLOG (connection->daemon, 1117 MHD_DLOG (connection->daemon,
1261 "Failed to send data: %s\n", STRERROR (errno)); 1118 "Failed to send data: %s\n", STRERROR (errno));
1262 connection_close_error(connection); 1119 connection_close_error (connection);
1263 return MHD_YES; 1120 return MHD_YES;
1264 } 1121 }
1265#if DEBUG_SEND_DATA 1122#if DEBUG_SEND_DATA
1266 fprintf(stderr, 1123 fprintf (stderr,
1267 "Sent DATA response: `%.*s'\n", 1124 "Sent DATA response: `%.*s'\n",
1268 ret, 1125 ret,
1269 &response->data[connection->messagePos - response->data_start]); 1126 &response->data[connection->messagePos - response->data_start]);
1270#endif 1127#endif
1271 connection->messagePos += ret; 1128 connection->messagePos += ret;
1272 if (connection->messagePos > response->total_size) 1129 if (connection->messagePos > response->total_size)
@@ -1277,11 +1134,12 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1277 (connection->headersReceived == 0)) 1134 (connection->headersReceived == 0))
1278 abort (); /* internal error */ 1135 abort (); /* internal error */
1279 MHD_destroy_response (response); 1136 MHD_destroy_response (response);
1280 if (connection->daemon->notify_completed != NULL) 1137 if (connection->daemon->notify_completed != NULL)
1281 connection->daemon->notify_completed(connection->daemon->notify_completed_cls, 1138 connection->daemon->notify_completed (connection->daemon->
1282 connection, 1139 notify_completed_cls,
1283 &connection->client_context, 1140 connection,
1284 MHD_REQUEST_TERMINATED_COMPLETED_OK); 1141 &connection->client_context,
1142 MHD_REQUEST_TERMINATED_COMPLETED_OK);
1285 connection->client_context = NULL; 1143 connection->client_context = NULL;
1286 connection->continuePos = 0; 1144 connection->continuePos = 0;
1287 connection->responseCode = 0; 1145 connection->responseCode = 0;
@@ -1297,14 +1155,15 @@ MHD_connection_handle_write (struct MHD_Connection *connection)
1297 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version))) 1155 (0 != strcasecmp (MHD_HTTP_VERSION_1_1, connection->version)))
1298 { 1156 {
1299 /* closed for reading => close for good! */ 1157 /* closed for reading => close for good! */
1300 if (connection->socket_fd != -1) { 1158 if (connection->socket_fd != -1)
1159 {
1301#if DEBUG_CLOSE 1160#if DEBUG_CLOSE
1302 MHD_DLOG (connection->daemon, 1161 MHD_DLOG (connection->daemon,
1303 "Closing connection (http 1.0 or end-of-stream for unknown content length)\n"); 1162 "Closing connection (http 1.0 or end-of-stream for unknown content length)\n");
1304#endif 1163#endif
1305 SHUTDOWN (connection->socket_fd, SHUT_RDWR); 1164 SHUTDOWN (connection->socket_fd, SHUT_RDWR);
1306 CLOSE (connection->socket_fd); 1165 CLOSE (connection->socket_fd);
1307 } 1166 }
1308 connection->socket_fd = -1; 1167 connection->socket_fd = -1;
1309 } 1168 }
1310 connection->version = NULL; 1169 connection->version = NULL;