plong

Unnamed repository; edit this file 'description' to name the repository.
git clone https://git.inz.fi/plong
Log | Files | Refs

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