http: assume data EOF if the connection terminates
[project/uclient.git] / uclient-http.c
index 195fa1c..5e5f996 100644 (file)
@@ -192,6 +192,9 @@ static void uclient_notify_eof(struct uclient_http *uh)
                        return;
        }
 
                        return;
        }
 
+       if (uh->content_length < 0 && uh->read_chunked >= 0)
+               uh->uc.data_eof = true;
+
        uclient_backend_set_eof(&uh->uc);
 
        if (uh->connection_close)
        uclient_backend_set_eof(&uh->uc);
 
        if (uh->connection_close)
@@ -663,28 +666,33 @@ static void __uclient_notify_read(struct uclient_http *uh)
                return;
 
        if (uh->state < HTTP_STATE_RECV_DATA) {
                return;
 
        if (uh->state < HTTP_STATE_RECV_DATA) {
-               char *sep;
+               char *sep, *next;
                int cur_len;
 
                do {
                int cur_len;
 
                do {
-                       sep = strstr(data, "\r\n");
+                       sep = strchr(data, '\n');
                        if (!sep)
                                break;
 
                        if (!sep)
                                break;
 
+                       next = sep + 1;
+                       if (sep > data && sep[-1] == '\r')
+                               sep--;
+
                        /* Check for multi-line HTTP headers */
                        if (sep > data) {
                        /* Check for multi-line HTTP headers */
                        if (sep > data) {
-                               if (!sep[2])
+                               if (!*next)
                                        return;
 
                                        return;
 
-                               if (isspace(sep[2]) && sep[2] != '\r') {
+                               if (isspace(*next) && *next != '\r' && *next != '\n') {
                                        sep[0] = ' ';
                                        sep[0] = ' ';
-                                       sep[1] = ' ';
+                                       if (sep + 1 < next)
+                                               sep[1] = ' ';
                                        continue;
                                }
                        }
 
                        *sep = 0;
                                        continue;
                                }
                        }
 
                        *sep = 0;
-                       cur_len = sep + 2 - data;
+                       cur_len = next - data;
                        uclient_parse_http_line(uh, data);
                        if (seq != uh->seq)
                                return;
                        uclient_parse_http_line(uh, data);
                        if (seq != uh->seq)
                                return;
@@ -1063,7 +1071,7 @@ uclient_http_read(struct uclient *cl, char *buf, unsigned int len)
        return len;
 }
 
        return len;
 }
 
-bool uclient_http_redirect(struct uclient *cl)
+int uclient_http_redirect(struct uclient *cl)
 {
        struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
        struct blobmsg_policy location = {
 {
        struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
        struct blobmsg_policy location = {
@@ -1095,7 +1103,9 @@ bool uclient_http_redirect(struct uclient *cl)
 
        free(cl->url);
        cl->url = url;
 
        free(cl->url);
        cl->url = url;
-       uclient_http_connect(cl);
+       if (uclient_http_connect(cl))
+               return -1;
+
        uclient_http_request_done(cl);
 
        return true;
        uclient_http_request_done(cl);
 
        return true;