Overview
Comment: | Updated to support HTTP Connection Keep-Alive |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: | b4fa45b6aa3bc1a7390f3ae961a921edd1f1be86 |
User & Date: | rkeene on 2014-10-13 08:04:09 |
Other Links: | manifest | tags |
References
2014-10-13
| ||
14:59 | Fixed file descriptor leaking introduced in [b4fa45b6aa] and made connection re-use more clean check-in: 679bcc1373 user: rkeene tags: trunk | |
Context
2014-10-13
| ||
08:12 | Filed 1.10 check-in: dd8a7297f3 user: rkeene tags: trunk, 1.10 | |
08:04 | Updated to support HTTP Connection Keep-Alive check-in: b4fa45b6aa user: rkeene tags: trunk | |
2014-08-31
| ||
18:07 | Updated to use a fallback mime.types file if specified one is unavailable check-in: 862bf6f56b user: rkeene tags: trunk | |
Changes
Modified filed.c from [9ca8af3757] to [d1e3cfdb7f].
90 90 off_t length; /*** Range length ***/ 91 91 } range; 92 92 93 93 struct { 94 94 int present; 95 95 char host[FILED_PATH_BUFFER_SIZE]; 96 96 } host; 97 + 98 + enum { 99 + FILED_CONNECTION_CLOSE, 100 + FILED_CONNECTION_KEEP_ALIVE 101 + } connection; 97 102 } headers; 98 103 }; 99 104 100 105 /* Log record */ 101 106 struct filed_log_entry { 102 107 /* Type of log entry */ 103 108 enum { ................................................................................ 685 690 686 691 /* Set to default values */ 687 692 range_start = 0; 688 693 range_end = 0; 689 694 range_request = 0; 690 695 range_length = -1; 691 696 buffer_st->headers.host.present = 0; 697 + buffer_st->headers.connection = FILED_CONNECTION_CLOSE; 692 698 693 699 buffer = buffer_st->tmpbuf; 694 700 buffer_len = sizeof(buffer_st->tmpbuf); 695 701 696 702 fgets_ret = fgets(buffer, buffer_len, fp); 697 703 if (fgets_ret == NULL) { 698 704 return(NULL); ................................................................................ 784 790 785 791 workbuffer = buffer + 5; 786 792 while (*workbuffer == ' ') { 787 793 workbuffer++; 788 794 } 789 795 790 796 strcpy(buffer_st->headers.host.host, workbuffer); 797 + } else if (strncasecmp(buffer, "Connection: Keep-Alive", 22) == 0) { 798 + buffer_st->headers.connection = FILED_CONNECTION_KEEP_ALIVE; 791 799 } 792 800 793 801 if (memcmp(buffer, "\r\n", 2) == 0) { 794 802 break; 795 803 } 796 804 } 797 805 ................................................................................ 887 895 fclose(fp); 888 896 889 897 return; 890 898 891 899 /* Currently unused: path */ 892 900 path = path; 893 901 } 902 + 903 +/* Convert an enum representing the "Connection" header value to a string */ 904 +static const char *filed_connection_str(int connection_value) { 905 + switch (connection_value) { 906 + case FILED_CONNECTION_CLOSE: 907 + return("close"); 908 + case FILED_CONNECTION_KEEP_ALIVE: 909 + return("keep-alive"); 910 + } 911 + 912 + return("close"); 913 +} 894 914 895 915 /* Handle a single request from a client */ 896 -static void filed_handle_client(int fd, struct filed_http_request *request, struct filed_log_entry *log, struct filed_options *options) { 916 +static int filed_handle_client(int fd, struct filed_http_request *request, struct filed_log_entry *log, struct filed_options *options) { 897 917 struct filed_fileinfo *fileinfo; 898 918 ssize_t sendfile_ret; 899 919 size_t sendfile_size; 900 920 off_t sendfile_offset, sendfile_sent, sendfile_len; 901 921 char *path; 902 922 char *date_current, date_current_b[64]; 903 923 int http_code; ................................................................................ 913 933 914 934 log->buffer[0] = '\0'; 915 935 log->http_code = -1; 916 936 log->reason = "fdopen_failed"; 917 937 918 938 filed_log_entry(log); 919 939 920 - return; 940 + return(0); 921 941 } 922 942 923 943 request = filed_get_http_request(fp, request, options); 924 944 925 945 if (request == NULL) { 926 946 log->buffer[0] = '\0'; 927 947 928 948 filed_error_page(fp, date_current, 500, FILED_REQUEST_METHOD_GET, "format", log); 929 949 930 - return; 950 + return(0); 931 951 } 932 952 933 953 path = request->path; 934 954 strcpy(log->buffer, path); 935 955 log->method = request->method; 936 956 937 957 /* If the requested path is a directory, redirect to index page */ 938 958 if (request->type == FILED_REQUEST_TYPE_DIRECTORY) { 939 959 filed_redirect_index(fp, date_current, path, log); 940 960 941 - return; 961 + return(0); 942 962 } 943 963 944 964 fileinfo = filed_open_file(path, &request->fileinfo); 945 965 if (fileinfo == NULL) { 946 966 filed_error_page(fp, date_current, 404, request->method, "open_failed", log); 947 967 948 - return; 968 + return(0); 949 969 } 950 970 951 971 if (request->headers.range.present) { 952 972 if (request->headers.range.offset != 0 || request->headers.range.length >= 0) { 953 973 if (request->headers.range.offset >= fileinfo->len) { 954 974 filed_error_page(fp, date_current, 416, request->method, "range_invalid", log); 955 975 956 976 close(fileinfo->fd); 957 977 958 - return; 978 + return(0); 959 979 } 960 980 961 981 if (request->headers.range.length == ((off_t) -1)) { 962 982 filed_log_msg_debug("Computing length to fit in bounds: fileinfo->len = %llu, request->headers.range.offset = %llu", 963 983 (unsigned long long) fileinfo->len, 964 984 (unsigned long long) request->headers.range.offset 965 985 ); ................................................................................ 979 999 http_code = 200; 980 1000 981 1001 /* Compute fake range parameters that includes the entire file */ 982 1002 request->headers.range.offset = 0; 983 1003 request->headers.range.length = fileinfo->len; 984 1004 } 985 1005 986 - fprintf(fp, "HTTP/1.1 %i OK\r\nDate: %s\r\nServer: filed\r\nLast-Modified: %s\r\nContent-Length: %llu\r\nAccept-Ranges: bytes\r\nContent-Type: %s\r\nConnection: close\r\nETag: \"%s\"\r\n", 1006 + fprintf(fp, "HTTP/1.1 %i OK\r\nDate: %s\r\nServer: filed\r\nLast-Modified: %s\r\nContent-Length: %llu\r\nAccept-Ranges: bytes\r\nContent-Type: %s\r\nConnection: %s\r\nETag: \"%s\"\r\n", 987 1007 http_code, 988 1008 date_current, 989 1009 fileinfo->lastmod, 990 1010 (unsigned long long) request->headers.range.length, 991 1011 fileinfo->type, 1012 + filed_connection_str(request->headers.connection), 992 1013 fileinfo->etag 993 1014 ); 994 1015 995 1016 if (http_code == 206) { 996 1017 fprintf(fp, "Content-Range: bytes %llu-%llu/%llu\r\n", 997 1018 (unsigned long long) request->headers.range.offset, 998 1019 (unsigned long long) (request->headers.range.offset + request->headers.range.length - 1), ................................................................................ 1075 1096 } 1076 1097 1077 1098 log->endtime = (time_t) -1; 1078 1099 log->sent_length = sendfile_sent; 1079 1100 1080 1101 filed_log_entry(log); 1081 1102 1082 - close(fileinfo->fd); 1103 + if (request->headers.connection != FILED_CONNECTION_KEEP_ALIVE) { 1104 + close(fileinfo->fd); 1083 1105 1084 - fclose(fp); 1106 + fclose(fp); 1085 1107 1086 - return; 1108 + return(0); 1109 + } 1110 + 1111 + return(1); 1087 1112 } 1088 1113 1089 1114 /* Handle incoming connections */ 1090 1115 static void *filed_worker_thread(void *arg_v) { 1091 1116 struct filed_worker_thread_args *arg; 1092 1117 struct filed_http_request request; 1093 1118 struct filed_log_entry *log, local_dummy_log; 1094 1119 struct filed_options *options; 1095 1120 struct sockaddr_in6 addr; 1096 1121 socklen_t addrlen; 1097 1122 int failure_count = 0, max_failure_count = FILED_MAX_FAILURE_COUNT; 1098 - int master_fd, fd; 1123 + int accept_new = 1; 1124 + int master_fd, fd = -1; 1099 1125 1100 1126 /* Read arguments */ 1101 1127 arg = arg_v; 1102 1128 1103 1129 master_fd = arg->fd; 1104 1130 options = &arg->options; 1105 1131 ................................................................................ 1116 1142 1117 1143 break; 1118 1144 } 1119 1145 1120 1146 log->type = FILED_LOG_TYPE_TRANSFER; 1121 1147 1122 1148 /* Accept a new client */ 1123 - addrlen = sizeof(addr); 1124 - fd = accept(master_fd, (struct sockaddr *) &addr, &addrlen); 1149 + if (accept_new) { 1150 + addrlen = sizeof(addr); 1151 + fd = accept(master_fd, (struct sockaddr *) &addr, &addrlen); 1152 + } 1125 1153 1126 1154 /* 1127 1155 * If we fail, make a note of it so we don't go into a loop of 1128 1156 * accept() failing 1129 1157 */ 1130 1158 if (fd < 0) { 1131 1159 /* Log the new connection */ ................................................................................ 1146 1174 log->port = addr.sin6_port; 1147 1175 } 1148 1176 1149 1177 /* Reset failure count*/ 1150 1178 failure_count = 0; 1151 1179 1152 1180 /* Handle socket */ 1153 - filed_handle_client(fd, &request, log, options); 1181 + accept_new = !filed_handle_client(fd, &request, log, options); 1154 1182 } 1155 1183 1156 1184 /* Report error */ 1157 1185 filed_log_msg("THREAD_DIED ABNORMAL"); 1158 1186 1159 1187 return(NULL); 1160 1188