#include #include #include #include #include #include #include "addr.h" #include "binding.h" #include "../io/log.h" static void create_udp_binding(UdpSocket* socket, uint16_t port) { if (create_udp_socket(V6, socket) < 0) { ERROR("Failed to create UDP socket: %s", strerror(errno)); exit(EXIT_FAILURE); } IpAddr addr; ip_addr_any6(&addr); SocketAddr socketaddr; create_socket_addr(port, addr, &socketaddr); if (bind_udp_socket(&socketaddr, socket) < 0) { ERROR("Failed to bind UDP socket on port %hu: %s", port, strerror(errno)); exit(EXIT_FAILURE); } } static void create_tcp_binding(TcpSocket* socket, uint16_t port) { if (create_tcp_socket(V6, socket) < 0) { ERROR("Failed to create TCP socket: %s", strerror(errno)); exit(EXIT_FAILURE); } IpAddr addr; ip_addr_any6(&addr); SocketAddr socketaddr; create_socket_addr(port, addr, &socketaddr); if (bind_tcp_socket(&socketaddr, socket) < 0) { ERROR("Failed to bind TCP socket on port %hu: %s", port, strerror(errno)); exit(EXIT_FAILURE); } if (listen_tcp_socket(socket, 5) < 0) { ERROR("Failed to listen on TCP socket: %s", strerror(errno)); exit(EXIT_FAILURE); } } void create_binding(BindingType type, uint16_t port, Binding* binding) { binding->type = type; if (type == UDP) { create_udp_binding(&binding->sock.udp, port); } else if(type == TCP) { create_tcp_binding(&binding->sock.tcp, port); } else { exit(EXIT_FAILURE); } } void free_binding(Binding* binding) { if (binding->type == UDP) { close_udp_socket(&binding->sock.udp); } else if(binding->type == TCP) { close_tcp_socket(&binding->sock.tcp); } } bool accept_connection(Binding* binding, Connection* connection) { connection->type = binding->type; if(binding->type == UDP) { connection->sock.udp.udp = binding->sock.udp; memset(&connection->sock.udp.clientaddr, 0, sizeof(SocketAddr)); return true; } if (accept_tcp_socket(&binding->sock.tcp, &connection->sock.tcp) < 0) { ERROR("Failed to accept TCP connection: %s", strerror(errno)); return false; } return true; } static void read_to_packet(uint8_t* buf, uint16_t len, Packet* packet) { PacketBuffer* pkbuffer = buffer_create(len); for (int i = 0; i < len; i++) { buffer_write(pkbuffer, buf[i]); } buffer_seek(pkbuffer, 0); read_packet(pkbuffer, packet); buffer_free(pkbuffer); } static bool read_udp(Connection* connection, Packet* packet) { uint8_t buffer[512]; int32_t n = read_udp_socket( &connection->sock.udp.udp, buffer, 512, &connection->sock.udp.clientaddr ); if (n < 0) { return false; } read_to_packet(buffer, n, packet); return true; } static bool read_tcp(Connection* connection, Packet* packet) { uint16_t len; if ( read_tcp_stream( &connection->sock.tcp, &len, sizeof(uint16_t) ) < 0) { return false; } uint8_t buffer[len]; if ( read_tcp_stream( &connection->sock.tcp, buffer, len ) < 0) { return false; } read_to_packet(buffer, len, packet); return true; } bool read_connection(Connection* connection, Packet* packet) { if (connection->type == UDP) { return read_udp(connection, packet); } else if (connection->type == TCP) { return read_tcp(connection, packet); } return false; } static bool write_udp(Connection* connection, uint8_t* buf, uint16_t len) { //if (len > 512) { buf[2] = buf[2] | 0x03; // len = 512; // } return write_udp_socket( &connection->sock.udp.udp, buf, len, &connection->sock.udp.clientaddr ) == len; } static bool write_tcp(Connection* connection, uint8_t* buf, uint16_t len) { len = htons(len); if (write_tcp_stream( &connection->sock.tcp, &len, sizeof(uint16_t) ) < 0) { return false; } if (write_tcp_stream( &connection->sock.tcp, buf, len ) < 0) { return false; } return true; } bool write_connection(Connection* connection, Packet* packet) { PacketBuffer* pkbuffer = buffer_create(64); write_packet(pkbuffer, packet); uint16_t len = buffer_get_size(pkbuffer); uint8_t* buffer = buffer_get_ptr(pkbuffer); bool success = false; if(connection->type == UDP) { success = write_udp(connection, buffer, len); } else if(connection->type == TCP) { success = write_tcp(connection, buffer, len); }; buffer_free(pkbuffer); return success; } void free_connection(Connection* connection) { if (connection->type == TCP) { close_tcp_stream(&connection->sock.tcp); } } static bool create_udp_request(SocketAddr* addr, Connection* request) { if ( create_udp_socket(addr->type, &request->sock.udp.udp) < 0) { ERROR("Failed to connect to UDP socket: %s", strerror(errno)); return false; } request->sock.udp.clientaddr = *addr; return true; } static bool create_tcp_request(SocketAddr* addr, Connection* request) { if( connect_tcp_stream(addr, &request->sock.tcp) < 0) { ERROR("Failed to connect to TCP socket: %s", strerror(errno)); return false; } return true; } bool create_request(BindingType type, SocketAddr* addr, Connection* request) { request->type = type; if (type == UDP) { return create_udp_request(addr, request); } else if (type == TCP) { return create_tcp_request(addr, request); } else { return true; } } bool request_packet(Connection* request, Packet* in, Packet* out) { if (!write_connection(request, in)) { return false; } if (!read_connection(request, out)) { return false; } return true; } void free_request(Connection* connection) { if (connection->type == UDP) { close_udp_socket(&connection->sock.udp.udp); } else if (connection->type == TCP) { close_tcp_stream(&connection->sock.tcp); } }