http.c (2314B)
1 #include <unistd.h> 2 #include <stdio.h> 3 #include <netdb.h> 4 #include <errno.h> 5 #include <sys/poll.h> 6 7 #include "http.h" 8 #include "minitls.h" 9 #include "buf.h" 10 11 int http_post(const char *server, 12 const char *port, 13 const char *path, 14 const struct buf *b, 15 struct buf *reply, 16 int *af, 17 struct tls *ctx) 18 { 19 char buffer[1024]; 20 struct addrinfo *res; 21 struct addrinfo *i; 22 struct addrinfo hints = { .ai_family = *af, .ai_socktype = SOCK_STREAM }; 23 ssize_t r; 24 ssize_t s; 25 int sock; 26 27 if ((r = getaddrinfo(server, port, &hints, &res))) 28 return r; 29 30 r = ENOENT; 31 for (i = res; i; i = i->ai_next) { 32 sock = socket(i->ai_family, i->ai_socktype, i->ai_protocol); 33 34 *af = i->ai_family; 35 if (!(r = connect(sock, i->ai_addr, i->ai_addrlen))) 36 break; 37 close(sock); 38 } 39 40 freeaddrinfo(res); 41 if (!i) 42 return r; 43 44 if ((r = snprintf(buffer, sizeof(buffer), 45 "POST %s HTTP/1.0\r\nHost: %s\r\nContent-Type: application/json\r\nContent-Length: %zu\r\n\r\n", 46 path, server, b->end - b->data)) >= (int)sizeof(buffer)) { 47 close(sock); 48 return ENOMEM; 49 } 50 51 if (ctx) { 52 if (tls_connect_socket(ctx, sock, server)) { 53 close(sock); 54 return -1; 55 } 56 57 if ((s = tls_write(ctx, buffer, r)) < r) { 58 tls_close(ctx); 59 tls_reset(ctx); 60 tls_configure(ctx, NULL); 61 close(sock); 62 return -1; 63 } 64 } else if ((s = write(sock, buffer, r)) < r) { 65 close(sock); 66 return -1; 67 } 68 69 if (ctx) { 70 if ((s = tls_write(ctx, b->data, b->end - b->data)) < b->end - b->data) { 71 tls_close(ctx); 72 tls_reset(ctx); 73 tls_configure(ctx, NULL); 74 close(sock); 75 return -1; 76 } 77 } else if ((s = write(sock, b->data, b->end - b->data)) < b->end - b->data) { 78 close(sock); 79 return -1; 80 } 81 82 if (reply) { 83 do { 84 if (ctx) 85 r = tls_read(ctx, reply->data, reply->end - reply->data); 86 else 87 r = read(sock, reply->data, reply->end - reply->data); 88 if (r < 0) { 89 if (ctx) { 90 if (r == TLS_WANT_POLLIN) { 91 poll(&(struct pollfd){ .fd = sock, .events = POLLIN }, 1, 0); 92 continue; 93 } 94 95 tls_close(ctx); 96 tls_reset(ctx); 97 tls_configure(ctx, NULL); 98 } 99 close(sock); 100 return -1; 101 } 102 reply->data += r; 103 } while (r && reply->data < reply->end); 104 } 105 106 if (ctx) { 107 tls_close(ctx); 108 tls_reset(ctx); 109 tls_configure(ctx, NULL); 110 } 111 112 close(sock); 113 114 return s; 115 } 116