serve

serve.git
git clone git://git.lenczewski.org/serve.git
Log | Files | Refs

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 }