Files

137 lines
2.9 KiB
C

/* mcsdb - LGPLv3 - Copyright 2011-2014 - pancake */
#include "mcsdb.h"
#include <sdb/types.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <poll.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdarg.h>
static char netbuf[MCSDB_MAX_BUFFER];
static size_t netbuflen = 0;
char *net_readnl(int fd) {
int i = -1;
char buf[MCSDB_MAX_BUFFER];
do {
i++;
if (i == sizeof (buf)) {
return NULL;
}
if (read (fd, buf+i, 1) != 1) {
return NULL;
}
} while (buf[i] != '\n');
buf[i - 1] = 0; // chop \r
return strdup (buf);
}
//NetSocket *net_accept(NetSocket *s) { }
int net_flush(int fd) {
int n;
if (netbuflen < 1) {
return 0;
}
if (fd == -1) {
fd = 1; //stdout
}
n = write (fd, netbuf, netbuflen);
netbuflen = 0;
return n;
}
int net_printf (int fd, const char *fmt, ...) {
int n;
char buf[MCSDB_MAX_BUFFER];
va_list ap;
va_start (ap, fmt);
n = vsnprintf (buf, sizeof (buf)-1, fmt, ap);
va_end (ap);
if (n < 0) {
return 0;
}
if (netbuflen+n > sizeof (netbuf)) {
net_flush (fd);
}
strcpy (netbuf + netbuflen, buf);
netbuflen += n;
return n;
}
void net_sockopt (int fd) {
#if __linux__
struct linger ling = {0, 0};
#endif
int flags = 1;
(void)setsockopt (fd, SOL_SOCKET, SO_REUSEADDR,
(void *)&flags, sizeof (flags));
#if __linux__
(void)setsockopt (fd, SOL_SOCKET, SO_LINGER,
(void *)&ling, sizeof (ling));
#endif
}
int net_listen (int port) {
int fd;
struct sockaddr_in sa;
if ((fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP))<0)
return -1;
net_sockopt (fd);
memset (&sa, 0, sizeof (sa));
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = htonl (INADDR_ANY);
sa.sin_port = htons (port);
if (bind (fd, (struct sockaddr *)&sa, sizeof (sa)) != 0) {
close (fd);
return -1;
}
(void)fcntl (fd, F_SETFL, O_NONBLOCK, 0);
signal (SIGPIPE, SIG_IGN);
if (listen (fd, 1) != -1) {
return fd;
}
close (fd);
return -1;
}
int net_close (int s) {
shutdown (s, SHUT_RDWR);
return close (s);
}
int net_connect(const char *host, const char *port) {
struct addrinfo hints, *res, *rp;
int s = -1, gai;
memset (&hints, 0, sizeof (struct addrinfo));
hints.ai_family = AF_INET; //UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_protocol = IPPROTO_TCP;
gai = getaddrinfo (host, port, &hints, &res);
if (gai != 0) {
printf ("Error in getaddrinfo: %s\n", gai_strerror (gai));
return -1;
}
if (res == NULL) {
printf ("Could not connect\n");
return -1;
}
for (rp = res; rp != NULL; rp = rp->ai_next) {
s = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (s == -1)
continue;
if (connect (s, rp->ai_addr, rp->ai_addrlen) != -1)
break;
close (s);
s = -1;
}
//fcntl (s, F_SETFL, O_NONBLOCK, 0); // //!block);
freeaddrinfo (res);
return s;
}