2019-02-08 13:28:39 +00:00
|
|
|
#include "net_tools.h"
|
|
|
|
|
2019-02-11 15:23:20 +00:00
|
|
|
// some code is inspired by https://github.com/millken/c-example/blob/master/epoll-example.c
|
|
|
|
// (which seems to be copied from https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/epoll-example.c )
|
|
|
|
|
2019-02-08 13:28:39 +00:00
|
|
|
int create_tcp_client(char* host, char* service) {
|
|
|
|
int err, sock;
|
|
|
|
struct addrinfo conf;
|
|
|
|
struct addrinfo *result, *cursor;
|
|
|
|
|
|
|
|
memset(&conf, 0, sizeof(struct addrinfo));
|
|
|
|
conf.ai_family = AF_UNSPEC;
|
|
|
|
conf.ai_socktype = SOCK_STREAM;
|
|
|
|
conf.ai_flags = 0;
|
|
|
|
conf.ai_protocol = 0;
|
|
|
|
|
|
|
|
err = getaddrinfo(host, service, &conf, &result);
|
|
|
|
if (err != 0) {
|
|
|
|
fprintf(stderr, "Error with getaddrinfo()\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (cursor = result; cursor != NULL; cursor = cursor->ai_next) {
|
|
|
|
sock = socket(cursor->ai_family, cursor->ai_socktype, cursor->ai_protocol);
|
|
|
|
if (sock == -1) continue;
|
|
|
|
if (connect(sock, cursor->ai_addr, cursor->ai_addrlen) != -1) break;
|
|
|
|
close(sock);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cursor == NULL) {
|
|
|
|
fprintf(stderr, "No connect worked\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
freeaddrinfo(result);
|
|
|
|
|
|
|
|
return sock;
|
|
|
|
}
|
|
|
|
|
2019-02-11 15:23:20 +00:00
|
|
|
int create_tcp_server(char* service) {
|
|
|
|
int err, sock;
|
|
|
|
struct addrinfo conf;
|
|
|
|
struct addrinfo *result, *cursor;
|
|
|
|
|
|
|
|
memset(&conf, 0, sizeof(struct addrinfo));
|
2019-02-11 16:04:12 +00:00
|
|
|
conf.ai_family = AF_INET; // AF_UNSPEC to listen on IPv6 or IPv4
|
2019-02-11 15:23:20 +00:00
|
|
|
conf.ai_socktype = SOCK_STREAM;
|
2019-02-11 16:04:12 +00:00
|
|
|
conf.ai_flags = 0; // AI_PASSIVE to listen on 0.0.0.0
|
2019-02-11 15:23:20 +00:00
|
|
|
conf.ai_protocol = 0;
|
|
|
|
|
|
|
|
err = getaddrinfo(NULL, service, &conf, &result);
|
|
|
|
if (err != 0) {
|
|
|
|
fprintf(stderr, "Error with getaddrinfo()\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (cursor = result; cursor != NULL; cursor = cursor->ai_next) {
|
|
|
|
sock = socket(cursor->ai_family, cursor->ai_socktype, cursor->ai_protocol);
|
|
|
|
if (sock == -1) continue;
|
|
|
|
if (bind(sock, cursor->ai_addr, cursor->ai_addrlen) != -1) break;
|
|
|
|
close(sock);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cursor == NULL) {
|
|
|
|
fprintf(stderr, "We failed to bind\n");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
freeaddrinfo (result);
|
|
|
|
|
|
|
|
return sock;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The idea is to get the file descriptor flags
|
|
|
|
* then we add to the bitmask O_NONBLOCK and set the
|
|
|
|
* new bitmask to the socket
|
|
|
|
*/
|
|
|
|
int make_socket_non_blocking(int fd) {
|
|
|
|
int err, flags;
|
|
|
|
flags = fcntl (fd, F_GETFL);
|
|
|
|
if (flags == -1) {
|
|
|
|
perror("Failed to get socket's flags via fcntl");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
flags |= O_NONBLOCK;
|
|
|
|
err = fcntl (fd, F_SETFL, flags);
|
|
|
|
if (err != 0) {
|
|
|
|
perror("Failed to set socket's flags via fcntl");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-02-08 13:28:39 +00:00
|
|
|
int read_entity(int fd, void* entity, int size) {
|
|
|
|
int remaining = size;
|
|
|
|
int total_read = 0;
|
|
|
|
|
|
|
|
while (remaining > 0) {
|
|
|
|
int nread = read(fd, ((char*)entity)+total_read, remaining);
|
|
|
|
if (nread == -1) {
|
|
|
|
return nread;
|
|
|
|
}
|
|
|
|
remaining -= nread;
|
|
|
|
total_read += nread;
|
|
|
|
}
|
|
|
|
return total_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fill_buffer(size_t* written, char* dest, void *src, size_t n) {
|
|
|
|
memcpy(dest+*written, src, n);
|
|
|
|
*written += n;
|
|
|
|
}
|