add support for querying local/remote address
[project/uclient.git] / uclient-http.c
index 8053be000f92a7588f6096463a99b0ebb194cc4b..ee354c7af6b9f1c167e6cbb5c4a4e74de243015a 100644 (file)
@@ -1,3 +1,20 @@
+/*
+ * uclient - ustream based protocol client library
+ *
+ * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
 #include <stdio.h>
 #include <ctype.h>
 #include <unistd.h>
@@ -479,11 +496,14 @@ uclient_http_send_headers(struct uclient_http *uh)
        uclient_http_add_auth_header(uh);
 
        ustream_printf(uh->us, "\r\n");
+
+       uh->state = HTTP_STATE_HEADERS_SENT;
 }
 
 static void uclient_http_headers_complete(struct uclient_http *uh)
 {
        enum auth_type auth_type = uh->auth_type;
+       socklen_t sl;
 
        uh->state = HTTP_STATE_RECV_DATA;
        uh->uc.meta = uh->meta.head;
@@ -496,10 +516,17 @@ static void uclient_http_headers_complete(struct uclient_http *uh)
                return;
        }
 
+       memset(&uh->uc.local_addr, 0, sizeof(uh->uc.local_addr));
+       memset(&uh->uc.remote_addr, 0, sizeof(uh->uc.remote_addr));
+
+       sl = sizeof(uh->uc.local_addr);
+       getsockname(uh->ufd.fd.fd, &uh->uc.local_addr.sa, &sl);
+       getpeername(uh->ufd.fd.fd, &uh->uc.remote_addr.sa, &sl);
+
        if (uh->uc.cb->header_done)
                uh->uc.cb->header_done(&uh->uc);
 
-       if (uh->req_type == REQ_HEAD) {
+       if (uh->req_type == REQ_HEAD || uh->uc.status_code == 204) {
                uh->eof = true;
                uclient_notify_eof(uh);
        }
@@ -782,7 +809,7 @@ uclient_http_set_request_type(struct uclient *cl, const char *type)
 }
 
 int
-uclient_http_reset_headers(struct uclient *cl, const char *name, const char *value)
+uclient_http_reset_headers(struct uclient *cl)
 {
        struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
 
@@ -816,10 +843,11 @@ uclient_http_send_data(struct uclient *cl, char *buf, unsigned int len)
 
        uclient_http_send_headers(uh);
 
-       ustream_printf(uh->us, "%X\r\n", len);
-       if (len > 0)
+       if (len > 0) {
+               ustream_printf(uh->us, "%X\r\n", len);
                ustream_write(uh->us, buf, len, false);
-       ustream_printf(uh->us, "\r\n");
+               ustream_printf(uh->us, "\r\n");
+       }
 
        return len;
 }
@@ -833,6 +861,8 @@ uclient_http_request_done(struct uclient *cl)
                return -1;
 
        uclient_http_send_headers(uh);
+       if (uh->req_type == REQ_POST)
+               ustream_printf(uh->us, "0\r\n\r\n");
        uh->state = HTTP_STATE_REQUEST_DONE;
 
        return 0;