diff options
author | Tyler Murphy <tylerm@tylerm.dev> | 2023-04-05 23:08:09 -0400 |
---|---|---|
committer | Tyler Murphy <tylerm@tylerm.dev> | 2023-04-05 23:08:09 -0400 |
commit | bb85374b79086cd8efde24d23a1bffeb97cae26b (patch) | |
tree | a36e2df6a89e567822820ac110afec6a13eacbf6 /src/server/addr.c | |
parent | finish dns and start webserver (diff) | |
download | wrapper-bb85374b79086cd8efde24d23a1bffeb97cae26b.tar.gz wrapper-bb85374b79086cd8efde24d23a1bffeb97cae26b.tar.bz2 wrapper-bb85374b79086cd8efde24d23a1bffeb97cae26b.zip |
new c version
Diffstat (limited to 'src/server/addr.c')
-rw-r--r-- | src/server/addr.c | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/src/server/addr.c b/src/server/addr.c new file mode 100644 index 0000000..982da13 --- /dev/null +++ b/src/server/addr.c @@ -0,0 +1,233 @@ +#include <netinet/in.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "addr.h" +#include "../io/log.h" + +void create_ip_addr(char* domain, IpAddr* addr) { + addr->type = V4; + memcpy(&addr->data.v4.s_addr, domain, 4); +} + +void create_ip_addr6(char* domain, IpAddr* addr) { + addr->type = V6; + memcpy(&addr->data.v6.__in6_u.__u6_addr8, domain, 16); +} + +void ip_addr_any(IpAddr* addr) { + addr->type = V4; + addr->data.v4.s_addr = htonl(INADDR_ANY); +} + +void ip_addr_any6(IpAddr* addr) { + addr->type = V6; + addr->data.v6 = in6addr_any; +} + +static struct sockaddr_in create_socket_addr_v4(IpAddr addr, uint16_t port) { + struct sockaddr_in socketaddr; + memset(&socketaddr, 0, sizeof(socketaddr)); + socketaddr.sin_family = AF_INET; + socketaddr.sin_port = htons(port); + socketaddr.sin_addr = addr.data.v4; + return socketaddr; +} + +static struct sockaddr_in6 create_socket_addr_v6(IpAddr addr, uint16_t port) { + struct sockaddr_in6 socketaddr; + memset(&socketaddr, 0, sizeof(socketaddr)); + socketaddr.sin6_family = AF_INET6; + socketaddr.sin6_port = htons(port); + socketaddr.sin6_addr = addr.data.v6; + return socketaddr; +} + +static size_t get_addr_len(AddrType type) { + if (type == V4) { + return sizeof(struct sockaddr_in); + } else if (type == V6) { + return sizeof(struct sockaddr_in6); + } else { + return 0; + } +} + +void create_socket_addr(uint16_t port, IpAddr addr, SocketAddr* socket) { + socket->type = addr.type; + if (addr.type == V4) { + socket->data.v4 = create_socket_addr_v4(addr, port); + } else if(addr.type == V6) { + socket->data.v6 = create_socket_addr_v6(addr, port); + } else { + ERROR("Tried to create socketaddr with invalid protocol type"); + exit(EXIT_FAILURE); + } + socket->len = get_addr_len(addr.type); +} + +void print_socket_addr(SocketAddr* addr, char* buffer) { + INIT_LOG_BOUNDS + if(addr->type == V4) { + APPEND(buffer, "%hhu.%hhu.%hhu.%hhu:%hu", + (uint8_t) ((uint32_t)addr->data.v4.sin_addr.s_addr >> 24), + (uint8_t) ((uint32_t)addr->data.v4.sin_addr.s_addr >> 16), + (uint8_t) ((uint32_t)addr->data.v4.sin_addr.s_addr >> 8), + (uint8_t) ((uint32_t)addr->data.v4.sin_addr.s_addr), + addr->data.v4.sin_port + ); + } else { + for(int i = 0; i < 8; i++) { + APPEND(buffer, "%02hhx%02hhx:", + addr->data.v6.sin6_addr.__in6_u.__u6_addr8[i*2 + 0], + addr->data.v6.sin6_addr.__in6_u.__u6_addr8[i*2 + 1] + ); + } + APPEND(buffer, ":[%hu]", addr->data.v6.sin6_port); + } +} + +#define ADDR_DOMAIN(addr, var) \ + struct sockaddr* var; \ + if (addr->type == V4) { \ + var = (struct sockaddr*) &addr->data.v4; \ + } else if (addr->type == V6) { \ + var = (struct sockaddr*) &addr->data.v6; \ + } else { \ + return -1; \ + } + +#define ADDR_AFNET(type, var) \ + int var; \ + if (type == V4) { \ + var = AF_INET; \ + } else if (type == V6) { \ + var = AF_INET6; \ + } else { \ + return -1; \ + } + +int32_t create_udp_socket(AddrType type, UdpSocket* sock) { + ADDR_AFNET(type, __domain) + sock->type = type; + sock->sockfd = socket(__domain, SOCK_DGRAM, 0); + return sock->sockfd; +} + +int32_t bind_udp_socket(SocketAddr* addr, UdpSocket* sock) { + if (addr->type == V6) { + int v6OnlyEnabled = 0; + int32_t res = setsockopt( + sock->sockfd, + IPPROTO_IPV6, + IPV6_V6ONLY, + &v6OnlyEnabled, + sizeof(v6OnlyEnabled) + ); + if (res < 0) return res; + } + ADDR_DOMAIN(addr, __addr) + return bind(sock->sockfd, __addr, addr->len); +} + +int32_t read_udp_socket(UdpSocket* socket, void* buffer, uint16_t len, SocketAddr* clientaddr) { + clientaddr->type = socket->type; + clientaddr->len = get_addr_len(socket->type); + ADDR_DOMAIN(clientaddr, __addr) + return recvfrom( + socket->sockfd, + buffer, + (size_t) len, + MSG_WAITALL, + __addr, + (uint32_t*) &clientaddr->len + ); +} + +int32_t write_udp_socket(UdpSocket* socket, void* buffer, uint16_t len, SocketAddr* clientaddr) { + ADDR_DOMAIN(clientaddr, __addr) + return sendto( + socket->sockfd, + buffer, + (size_t) len, + MSG_CONFIRM, + __addr, + (uint32_t) clientaddr->len + ); +} + +int32_t close_udp_socket(UdpSocket* socket) { + return close(socket->sockfd); +} + +int32_t create_tcp_socket(AddrType type, TcpSocket* sock) { + ADDR_AFNET(type, __domain) + sock->type = type; + sock->sockfd = socket(__domain, SOCK_STREAM, 0); + return sock->sockfd; +} + +int32_t bind_tcp_socket(SocketAddr* addr, TcpSocket* sock) { + if (addr->type == V6) { + int v6OnlyEnabled = 0; + int32_t res = setsockopt( + sock->sockfd, + IPPROTO_IPV6, + IPV6_V6ONLY, + &v6OnlyEnabled, + sizeof(v6OnlyEnabled) + ); + if (res < 0) return res; + } + ADDR_DOMAIN(addr, __addr) + return bind(sock->sockfd, __addr, addr->len); +} + +int32_t listen_tcp_socket(TcpSocket* socket, uint32_t max) { + return listen(socket->sockfd, max); +} + +int32_t accept_tcp_socket(TcpSocket* socket, TcpStream* stream) { + stream->clientaddr.type = socket->type; + memset(&stream->clientaddr, 0, sizeof(SocketAddr)); + SocketAddr* addr = &stream->clientaddr; + ADDR_DOMAIN(addr, __addr) + stream->streamfd = accept( + socket->sockfd, + __addr, + (uint32_t*) &stream->clientaddr.len + ); + return stream->streamfd; +} + +int32_t close_tcp_socket(TcpSocket* socket) { + return close(socket->sockfd); +} + +int32_t connect_tcp_stream(SocketAddr* servaddr, TcpStream* stream) { + TcpSocket socket; + int32_t res = create_tcp_socket(servaddr->type, &socket); + if (res < 0) return res; + stream->clientaddr = *servaddr; + stream->streamfd = socket.sockfd; + ADDR_DOMAIN(servaddr, __addr) + return connect( + socket.sockfd, + __addr, + servaddr->len + ); +} + +int32_t read_tcp_stream(TcpStream* stream, void* buffer, uint16_t len) { + return recv(stream->streamfd, buffer, len, 0); +} + +int32_t write_tcp_stream(TcpStream* stream, void* buffer, uint16_t len) { + return send(stream->streamfd, buffer, len, MSG_NOSIGNAL); +} + +int32_t close_tcp_stream(TcpStream* stream) { + return close(stream->streamfd); +} |