netc

A simple C library for opening network sockets using linux syscalls.
git clone git://depsterr.com/git/netc
Log | Files | Refs | README | LICENSE

netc.c (2852B)


      1 /* netc, a simple c networking library.
      2    This all code in this library is licensed under the MIT LICENSE unless otherwise specified.
      3    See the LICENSE file for more details on the MIT LICENSE and read the comments in this file
      4    for more information on licensing */
      5 
      6 #include <sys/socket.h>
      7 #include <sys/stat.h>
      8 #include <sys/types.h>
      9 
     10 #include <fcntl.h>
     11 #include <netdb.h>
     12 #include <unistd.h>
     13 
     14 #include <stdio.h>
     15 #include <stdlib.h>
     16 #include <string.h>
     17 
     18 typedef enum NetcError {
     19 	NETC_ERROR_TOP = 0,
     20 	GET_ADDR_INFO = -1,
     21 	OPEN_CONNECTION = -2,
     22 	SET_SOCK_OPT = -3,
     23 	CLOSE = -4,
     24 	BIND = -5,
     25 	LISTEN = -6,
     26 	NETC_ERROR_BOT = -7,
     27 } NetcError;
     28 
     29 const char* NetcErrorStrings[] = {
     30 	[GET_ADDR_INFO * -1] = "Call to getaddrinfo failed.",
     31 	[OPEN_CONNECTION * -1] = "Unable to open a connection.",
     32 	[SET_SOCK_OPT * -1] = "Unable to set socket options.",
     33 	[CLOSE * -1] = "Unable to close socket.",
     34 	[BIND * -1] = "Unable to bind to address.",
     35 	[LISTEN * -1] = "Unable to mark socket as listener.",
     36 };
     37 
     38 const char* netc_decode_error(NetcError err) {
     39 	return (err > NETC_ERROR_BOT && err < NETC_ERROR_TOP) ? NetcErrorStrings[err * -1] : "Not a NetcError.";
     40 }
     41 
     42 /* thank you https://c9x.me/irc/ */
     43 /* c9x placed their code in public domain, as such I place the contents of this function in public domain */
     44 int netc_open(const char* host, const char* port) {
     45 	struct addrinfo hints, *res = NULL;
     46 	int fd = -1;
     47 
     48 	memset(&hints, 0, sizeof(hints));
     49 	hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */
     50 	hints.ai_flags = AI_NUMERICSERV; /* No name lookup */
     51 	hints.ai_socktype = SOCK_STREAM;
     52 	if(getaddrinfo(host, port, &hints, &res))
     53 		return GET_ADDR_INFO;
     54 
     55 	for(;res;res = res->ai_next) {
     56 		if ((fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0)
     57 			continue;
     58 		if (connect(fd, res->ai_addr, res->ai_addrlen) < 0) {
     59 			close(fd);
     60 			continue;
     61 		}
     62 		break;
     63 	}
     64 
     65 	if (fd < 0)
     66 		return OPEN_CONNECTION;
     67 
     68 	freeaddrinfo(res);
     69 
     70 	return fd;
     71 }
     72 
     73 /* thank you http://tools.suckless.org/quark/ */
     74 /* In additon to the MIT LICENSE This function is licensed under the ISC license,
     75    see the ISCLICENSE file or https://git.suckless.org/quark/file/LICENSE.html */
     76 int netc_listen(const char* host, const char* port, ssize_t connections) {
     77 	struct addrinfo *ai, *p, hints = { .ai_flags = AI_NUMERICSERV, .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
     78 	int fd = -1;
     79 
     80 	if (getaddrinfo(host, port, &hints, &ai))
     81 		return GET_ADDR_INFO;
     82 
     83 	for (p = ai; p; p = p->ai_next) {
     84 		if ((fd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
     85 			continue;
     86 		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0)
     87 			return SET_SOCK_OPT;
     88 		if (bind(fd, p->ai_addr, p->ai_addrlen) < 0) {
     89 			close(fd);
     90 			continue;
     91 		}
     92 		break;
     93 	}
     94 
     95 	freeaddrinfo(ai);
     96 
     97 	if (!p)
     98 		return BIND;
     99 
    100 	if (listen(fd, connections) < 0)
    101 		return LISTEN;
    102 
    103 	return fd;
    104 }