embox
109 строк · 2.3 Кб
1
2#include <stdbool.h>3#include <assert.h>4#include <string.h>5#include <stdlib.h>6#include <stdio.h>7#include <unistd.h>8#include <poll.h>9
10#include <sys/uio.h>11#include <util/math.h>12
13#include "cnc_ipc.h"14
15#define SSE_HEADER "data: \""16#define SSE_FOOTER "\"\n\n"17
18static int cnc_ipc_get_input_fd(void) {19char *cnc_in;20if (!(cnc_in = getenv(CNCIPC_IN))) {21printf("Error: IPC not found");22return 0;23}24
25return atoi(cnc_in);26}
27
28static int memcpy_iov(void *dst, size_t dst_len, struct iovec *iov, int iovlen) {29int i_iov;30void *bp;31int bp_len;32
33bp = dst;34bp_len = dst_len;35for (i_iov = 0; i_iov < iovlen; ++i_iov) {36const int to_write = min(iov[i_iov].iov_len, bp_len);37memcpy(bp, iov[i_iov].iov_base, to_write);38bp += to_write;39bp_len -= to_write;40}41
42return bp - dst;43}
44
45int main(int argc, char *argv[]) {46const int sock = STDOUT_FILENO;47const int ipc_in = cnc_ipc_get_input_fd();48char buf[128], out_buf[64];49struct pollfd fds[2];50struct iovec iov[3];51bool sock_conn, ipc_has_data;52int buf_len;53
54fds[0].fd = ipc_in;55fds[0].events = POLLIN | POLLERR;56fds[1].fd = sock;57fds[1].events = POLLERR;58
59buf_len = snprintf(buf, sizeof(buf),60"HTTP/1.1 200 OK\r\n"61"Content-Type: text/event-stream\r\n"62"Cache-Control: no-cache\r\n"63"Connection: keep-alive\r\n"64"\r\n");65
66iov[0].iov_base = SSE_HEADER;67iov[0].iov_len = strlen(SSE_HEADER);68iov[2].iov_base = SSE_FOOTER;69iov[2].iov_len = strlen(SSE_FOOTER);70
71ipc_has_data = false;72sock_conn = 0 < write(sock, buf, buf_len);73while (sock_conn) {74if (poll(fds, 2, -1) > 0) {75sock_conn = !(fds[1].revents & POLLERR);76ipc_has_data = fds[0].revents & POLLIN;77}78
79if (sock_conn && ipc_has_data) {80int buf_o;81while(1) {82buf_len = read(ipc_in, buf, sizeof(buf));83if (buf_len > 0) {84break;85}86usleep(1000);87}88
89buf_o = 0;90while (buf_o < buf_len) {91char *eom = memchr(buf + buf_o, '\n', buf_len - buf_o);92const int body_len = eom ? eom - (buf + buf_o) : buf_len - buf_o;93int write_len;94
95iov[1].iov_base = buf + buf_o;96iov[1].iov_len = body_len;97
98write_len = memcpy_iov(out_buf, sizeof(out_buf), iov, 3);99sock_conn = 0 < write(STDOUT_FILENO, out_buf, write_len);100if (!sock_conn) {101break;102}103
104buf_o += body_len + 1;105}106}107}108
109return 0;110}
111