#include c_err_t c_SockAddr_Init(c_SockAddr_t* self, int family, const char* ip, uint16_t port) { if (!self ) return C_ERR_PARAM; /* Wipe the target memory layout clear up front to prevent uninitialized garbage bits */ memset(self, 0, sizeof(c_SockAddr_t)); /* 1. Parse and initialize as an IPv4 Address */ if (family == AF_INET) { self->ipv4.sin_family = AF_INET; self->ipv4.sin_port = htons(port); self->size = sizeof(self->ipv4); if (ip) { if (inet_pton(AF_INET, ip, &(self->ipv4.sin_addr)) == 1) { return C_ERR_OK; }else { return C_ERR_FAIL; /* Invalid IPv4 string format */ } }else { self->ipv4.sin_addr.s_addr = htonl(INADDR_ANY); } return C_ERR_OK; } /* 2. Parse and initialize as an IPv6 Address */ if (family == AF_INET6) { self->ipv6.sin6_family = AF_INET6; self->ipv6.sin6_port = htons(port); self->size = sizeof(self->ipv6); if (ip) { if (inet_pton(AF_INET6, ip, &(self->ipv6.sin6_addr)) == 1) { return C_ERR_OK; }else { return C_ERR_FAIL;/* Invalid IPv6 string format */ } }else { self->ipv6.sin6_addr = in6addr_any; } return C_ERR_OK; } /* 3. Return an parameter error if an unsupported address family parameter is requested */ return C_ERR_PARAM; } c_err_t c_SockAddr_ToString(const c_SockAddr_t* self, char* out_str, c_size_t str_cap) { if (!self || !out_str || str_cap == 0) return C_ERR_PARAM; const void* src_addr = NULL; int family = self->ipv4.sin_family; if (family == AF_INET) { src_addr = &(self->ipv4.sin_addr); } else if (family == AF_INET6) { src_addr = &(self->ipv6.sin6_addr); } else { return C_ERR_FAIL; /* Unknown address family variant */ } if (inet_ntop(family, src_addr, out_str, (size_t)str_cap) == NULL) { return C_ERR_OUTOFBOUND; /* String buffer capacity limit was too small */ } return C_ERR_OK; }