#include #include #include #include #include #include #include #include "addr.h" #include "binding.h" 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) ) < 2) { return false; } len = ntohs(len); uint8_t buffer[len]; if (read_tcp_stream( &connection->sock.tcp, buffer, len ) < len) { return false; } read_to_packet(buffer, len, packet); return true; } static 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) { uint16_t net_len = htons(len); if (write_tcp_stream( &connection->sock.tcp, &net_len, sizeof(uint16_t) ) < 0) { return false; } if (write_tcp_stream( &connection->sock.tcp, buf, len ) < 0) { return false; } return true; } static 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) { 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) { 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); } }