net.c (2867B)
1 #include "website.h" 2 3 int 4 ioring_init(struct io_uring *ioring) 5 { 6 /* NOTE: we want to ensure that we can submit one operation for each 7 * connection in the worst case, as well as a single multihit 8 * accept for the server socket, so size our ioring submission 9 * queue appropriately. 10 */ 11 unsigned entries = 1 + (CONNECTION_POOL_CAPACITY * CONNECTION_CONCURRENT_OPS); 12 13 return -io_uring_queue_init(entries, ioring, 0); 14 } 15 16 void 17 enqueue_ioreq(struct io_uring *ioring, struct ioreq *ioreq) 18 { 19 struct io_uring_sqe *sqe = io_uring_get_sqe(ioring); 20 if (!sqe) { 21 submit_ioreqs(ioring); 22 sqe = io_uring_get_sqe(ioring); 23 } 24 25 assert(sqe); 26 27 switch (ioreq->type) { 28 case IOREQ_ACCEPT: 29 io_uring_prep_multishot_accept(sqe, 30 ioreq->fd, 31 ioreq->accept.addr, 32 ioreq->accept.addrlen, 33 ioreq->accept.flags); 34 break; 35 36 case IOREQ_RECV: 37 io_uring_prep_recv(sqe, 38 ioreq->fd, 39 ioreq->recv.buf, 40 ioreq->recv.len, 41 ioreq->recv.flags); 42 break; 43 44 case IOREQ_SEND: 45 io_uring_prep_send(sqe, 46 ioreq->fd, 47 ioreq->send.buf, 48 ioreq->send.len, 49 ioreq->send.flags); 50 break; 51 52 case IOREQ_READ: 53 io_uring_prep_read(sqe, 54 ioreq->fd, 55 ioreq->read.buf, 56 ioreq->read.len, 57 ioreq->read.off); 58 break; 59 60 case IOREQ_CLOSE: 61 io_uring_prep_close(sqe, 62 ioreq->fd); 63 break; 64 } 65 66 io_uring_sqe_set_data(sqe, ioreq); 67 } 68 69 extern inline void 70 enqueue_accept(struct io_uring *ioring, struct ioreq *req, int fd, 71 struct sockaddr *addr, socklen_t *addrlen, int flags); 72 73 extern inline void 74 enqueue_recv(struct io_uring *ioring, struct ioreq *req, int fd, 75 void *buf, size_t len, int flags); 76 77 extern inline void 78 enqueue_send(struct io_uring *ioring, struct ioreq *req, int fd, 79 void *buf, size_t len, int flags); 80 81 extern inline void 82 enqueue_read(struct io_uring *ioring, struct ioreq *req, int fd, 83 void *buf, size_t len, uint64_t off); 84 85 extern inline void 86 enqueue_close(struct io_uring *ioring, struct ioreq *req, int fd); 87 88 void 89 submit_ioreqs(struct io_uring *ioring) 90 { 91 io_uring_submit(ioring); 92 } 93 94 int 95 create_server_socket(char const *restrict host, char const *restrict port) 96 { 97 struct addrinfo hints = { 98 .ai_family = AF_UNSPEC, 99 .ai_socktype = SOCK_STREAM, 100 .ai_protocol = IPPROTO_TCP, 101 .ai_flags = AI_NUMERICSERV, 102 }, *addrinfo, *ptr; 103 104 int res; 105 if ((res = getaddrinfo(host, port, &hints, &addrinfo))) { 106 fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(res)); 107 return -1; 108 } 109 110 int fd; 111 for (ptr = addrinfo; ptr; ptr = ptr->ai_next) { 112 fd = socket(ptr->ai_family, ptr->ai_socktype | O_CLOEXEC, ptr->ai_protocol); 113 if (fd < 0) 114 continue; 115 116 if (bind(fd, ptr->ai_addr, ptr->ai_addrlen) == 0) 117 break; 118 119 close(fd); 120 } 121 122 freeaddrinfo(addrinfo); 123 124 if (!ptr) /* failed to bind to any addresses */ 125 return -1; 126 127 return fd; 128 }