tor_multipath_voip/src/net_tools.c

195 lines
5.4 KiB
C
Raw Normal View History

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-11 22:40:37 +00:00
int create_ip_client(char* host, char* service, int type) {
2019-02-12 18:29:00 +00:00
int err, sock, enable;
2019-02-08 13:28:39 +00:00
struct addrinfo conf;
struct addrinfo *result, *cursor;
memset(&conf, 0, sizeof(struct addrinfo));
conf.ai_family = AF_UNSPEC;
2019-02-11 22:40:37 +00:00
conf.ai_socktype = type;
2019-02-08 13:28:39 +00:00
conf.ai_flags = 0;
conf.ai_protocol = 0;
2019-02-12 18:29:00 +00:00
enable = 1;
2019-02-08 13:28:39 +00:00
err = getaddrinfo(host, service, &conf, &result);
if (err != 0) {
2019-02-11 22:40:37 +00:00
fprintf(stderr, "Error with getaddrinfo() for %s:%s\n",host,service);
2019-02-08 13:28:39 +00:00
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;
2019-02-12 18:29:00 +00:00
err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
if (err < 0) {
fprintf(stderr, "Error setting socket to SO_REUSEADDR\n");
exit(EXIT_FAILURE);
}
2019-02-08 13:28:39 +00:00
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 22:40:37 +00:00
int create_tcp_client(char* host, char* service) {
2019-03-27 15:24:39 +00:00
int sock = create_ip_client (host, service, SOCK_STREAM);
int activate = 1;
int err;
err = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &activate, sizeof(activate));
if (err < 0) {
perror("setsockopt TCP_NODELAY");
exit(EXIT_FAILURE);
}
return sock;
2019-02-11 22:40:37 +00:00
}
int create_udp_client(char* host, char* service) {
return create_ip_client (host, service, SOCK_DGRAM);
}
2019-02-22 15:01:22 +00:00
int create_ip_server(char* host, char* service, int type) {
2019-02-12 18:29:00 +00:00
int err, sock, enable;
2019-02-11 15:23:20 +00:00
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
conf.ai_socktype = type;
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;
2019-02-12 18:29:00 +00:00
enable = 1;
2019-02-22 15:01:22 +00:00
err = getaddrinfo(host, service, &conf, &result);
2019-02-11 15:23:20 +00:00
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;
2019-02-12 18:29:00 +00:00
err = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
if (err < 0) {
fprintf(stderr, "Error setting socket to SO_REUSEADDR\n");
exit(EXIT_FAILURE);
}
2019-02-11 15:23:20 +00:00
if (bind(sock, cursor->ai_addr, cursor->ai_addrlen) != -1) break;
2019-02-12 18:29:00 +00:00
perror("Bind failed");
2019-02-11 15:23:20 +00:00
close(sock);
}
if (cursor == NULL) {
2019-02-12 16:47:14 +00:00
fprintf(stderr, "We failed to create socket or bind\n");
2019-02-11 15:23:20 +00:00
exit(EXIT_FAILURE);
}
freeaddrinfo (result);
return sock;
}
2019-02-22 15:01:22 +00:00
int create_tcp_server(char* host, char* service) {
2019-03-27 15:24:39 +00:00
int sock = create_ip_server (host, service, SOCK_STREAM);
int activate = 1;
int err;
err = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &activate, sizeof(activate));
if (err < 0) {
perror("setsockopt TCP_NODELAY");
exit(EXIT_FAILURE);
}
2019-03-27 16:31:46 +00:00
2019-03-27 15:24:39 +00:00
return sock;
}
2019-02-22 15:01:22 +00:00
int create_udp_server(char* host, char* service) {
return create_ip_server (host, service, SOCK_DGRAM);
}
2019-02-11 15:23:20 +00:00
/*
* 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;
}
2019-02-11 21:40:00 +00:00
/*
* Trying with Level Triggered for now --------
* Be careful, if configured as edge triggered and not level triggered
* You need to read everything before going back to epoll
* Which means keeping state too
*/
2019-02-12 16:12:20 +00:00
void add_fd_to_epoll(int epollfd, int fd, uint32_t flags) {
int err = make_socket_non_blocking (fd);
if (err == -1) {
fprintf(stderr, "Unable to set fd=%d to non blocking\n", fd);
exit(EXIT_FAILURE);
}
2019-02-11 21:40:00 +00:00
2019-02-12 16:12:20 +00:00
struct epoll_event current_event = {0};
2019-02-11 21:40:00 +00:00
//current_event.events = EPOLLIN | EPOLLET;
2019-02-12 10:17:37 +00:00
current_event.events = flags;
2019-02-11 21:40:00 +00:00
current_event.data.fd = fd;
if (epoll_ctl (epollfd, EPOLL_CTL_ADD, fd, &current_event) == -1) {
perror("Failed to add a file descriptor to epoll with epoll_ctl");
exit(EXIT_FAILURE);
}
}
2019-03-22 16:14:35 +00:00
void update_fd_epoll(int epollfd, int fd, uint32_t flags) {
struct epoll_event current_event = {0};
current_event.events = flags;
current_event.data.fd = fd;
if (epoll_ctl (epollfd, EPOLL_CTL_MOD, fd, &current_event) == -1) {
perror("Failed to update a file descriptor to epoll with epoll_ctl");
exit(EXIT_FAILURE);
}
}