#include <stdlib.h>
#include <inttypes.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>

void logexit(const char *msg){
    perror(msg);
    exit(EXIT_FAILURE);
}

int addrparse(const char* addrstr, const char* portstr, struct sockaddr_storage* storage){
    if(addrstr == NULL || portstr == NULL){
        return -1;
    }

    uint16_t port = (uint16_t)atoi(portstr); // unsigned short
    if(port == 0){
        return -1;
    }
    port = htons(port); // host to network short

    /* %%%%%% IPv4 %%%%%% */
    struct in_addr inaddr4; // 32-bit IP Adress
    if(inet_pton(AF_INET, addrstr, &inaddr4)){
        struct sockaddr_in *addr4 = (struct sockaddr_in*)storage;
        addr4->sin_addr = inaddr4;
        addr4->sin_family = AF_INET;
        addr4->sin_port = port;
        return 0;
    }

    /* %%%%%% IPv6 %%%%%% */
    struct in6_addr inaddr6; // 128-bit IPv6 Adress
    if(inet_pton(AF_INET6, addrstr, &inaddr6)){
        struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)storage;
        addr6->sin6_family = AF_INET6;
        addr6->sin6_port = port;
        addr6->sin6_addr = inaddr6;
        memcpy(&(addr6->sin6_addr), &inaddr6, sizeof(inaddr6));
        return 0;
    }

    return -1;
}

void addrtostr(const struct sockaddr* addr, char* str, size_t strsize){
    int version;
    char addrstr[INET6_ADDRSTRLEN + 1] = "";
    uint16_t port;

    if(addr->sa_family == AF_INET){
        version = 4;
        struct sockaddr_in* addr4 = (struct sockaddr_in*)addr;
        if(!inet_ntop(AF_INET, &(addr4->sin_addr), addrstr, INET6_ADDRSTRLEN + 1)){
            logexit("ntop");
        }
        port = ntohs(addr4->sin_port); //network to host short
    }
    else if(addr->sa_family == AF_INET6){
        version = 6;
        struct sockaddr_in6* addr6 = (struct sockaddr_in6*)addr;
        if(!inet_ntop(AF_INET6, &(addr6->sin6_addr), addrstr, INET6_ADDRSTRLEN + 1)){
            logexit("ntop");
        }
        port = ntohs(addr6->sin6_port); //network to host short
    }
    else{
        logexit("Unknown Protocol Family.");
    }

    snprintf(str, strsize, "IPv%d %s %hu", version, addrstr, port);
}

int server_sockaddr_init(const char* proto, const char* portstr, struct sockaddr_storage* storage) {
    
    uint16_t port = (uint16_t)atoi(portstr); // unsigned short
    if(port == 0){
        return -1;
    }
    port = htons(port); // host to network short

    memset(storage, 0, sizeof(*storage));

    /* %%%%%% IPv4 %%%%%% */
    if(strcmp(proto, "v4") == 0){
        struct sockaddr_in *addr4 = (struct sockaddr_in*)storage;
        addr4->sin_addr.s_addr = INADDR_ANY;
        addr4->sin_family = AF_INET;
        addr4->sin_port = port;
        return 0;

    }

    /* %%%%%% IPv6 %%%%%% */
    else if(strcmp(proto, "v6") == 0){
        struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)storage;
        addr6->sin6_family = AF_INET6;
        addr6->sin6_port = port;
        addr6->sin6_addr = in6addr_any;
        return 0;
    }

    /* %%%%%% ERROR %%%%%% */
    else{
        return -1;
    }
}

int len(unsigned char* msg){

    int count = 0;

    while(msg[count] != '\0'){
        count++;
    }

    return count;
}
{'avg_line_length': 26.81512605042017, 'max_line_length': 100, 'alphanum_fraction': 0.577875274208712, 'licenses': ['MIT'], 'repository_name': 'jhonatanscruz/Client-Server', 'path': 'src/encrypted-message-client/common.c', 'size': 3191, 'lang': 'C'}