Skip to content
Extraits de code Groupes Projets
utils.c 6,37 ko
Newer Older
  • Learn to ignore specific revisions
  • #include "utils.h"
    
    
    
    const char * real_address(const char *address, struct sockaddr_in6 *rval)
    {
        struct addrinfo hints;
        struct addrinfo *result; 
        memset(&hints, 0, sizeof(hints));
        hints.ai_family = AF_INET6;     
        hints.ai_socktype = SOCK_DGRAM;
        hints.ai_flags  = AI_CANONNAME; 
        hints.ai_protocol = 0;
        int res = getaddrinfo(address, NULL, &hints, &result);
        if ( res != 0 )
            return gai_strerror(res);
        rval = (struct sockaddr_in6 *) memcpy( (void *) rval, result->ai_addr, sizeof(struct sockaddr_in6));
        freeaddrinfo(result);
        return NULL;
    }
    
    
    void ipv6_to_str_unexpanded(char *str, const struct in6_addr *addr) {
       sprintf(str, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
                     (int)addr->s6_addr[0], (int)addr->s6_addr[1],
                     (int)addr->s6_addr[2], (int)addr->s6_addr[3],
                     (int)addr->s6_addr[4], (int)addr->s6_addr[5],
                     (int)addr->s6_addr[6], (int)addr->s6_addr[7],
                     (int)addr->s6_addr[8], (int)addr->s6_addr[9],
                     (int)addr->s6_addr[10], (int)addr->s6_addr[11],
                     (int)addr->s6_addr[12], (int)addr->s6_addr[13],
                     (int)addr->s6_addr[14], (int)addr->s6_addr[15]);
    }
    
    
    int create_socket_bind(struct sockaddr_in6 * source_addr)
    {
        // TODO: Create a IPv6 socket supporting datagrams
        int sock = socket(AF_INET6, SOCK_DGRAM, 0);
        // TODO: Bind it to the source
        int err  = bind(sock, (struct sockaddr *) source_addr, sizeof(struct sockaddr_in6));
        if (err == -1) 
            return -1;
    
        char text[100];
        ipv6_to_str_unexpanded(text, &(source_addr->sin6_addr));
        //const char * addr_str = inet_ntop(AF_INET6, (void *) &(source_addr->sin6_addr), text, 100);
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        DEBUG("Successfully bound to IPv6 address : %s, port : %d", text, ntohs(source_addr->sin6_port));
    
        return sock;
    }
    
    
    int create_socket_connect(struct sockaddr_in6 * dest_addr)
    {
        int sock = socket(AF_INET6, SOCK_DGRAM, 0);
        int err  = connect(sock, (struct sockaddr *) dest_addr, sizeof(*dest_addr));
        if (err == -1) 
            return -1;
        char text[100];
        ipv6_to_str_unexpanded(text, &(dest_addr->sin6_addr));
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        DEBUG("Successfully connected to IPv6 addresss: %s, port : %d", text, ntohs(dest_addr->sin6_port));
    
        return sock;
    }
    
    
    int create_socket(struct sockaddr_in6 *source_addr, int src_port, struct sockaddr_in6 *dest_addr, int dst_port)
    {
    
    Vany Ingenzi's avatar
    Vany Ingenzi a validé
        if ( source_addr != NULL && dest_addr == NULL )
    
        {
            source_addr->sin6_port = htons(src_port);
            return create_socket_bind(source_addr);
        } else if ( source_addr == NULL && dest_addr != NULL ){
            dest_addr->sin6_port   = htons(dst_port);
            return create_socket_connect(dest_addr);
        }
        return -1;
    }
    
    
    int wait_for_client(int sfd)
    
        int MAX_MESSAGE_SIZE = 1024;
        uint8_t buff[MAX_MESSAGE_SIZE];   // allocate the receive buffer on the stack
    
        struct sockaddr_storage peer_addr;  // allocate the peer's address on the stack. It will be initialized when we receive a message
        socklen_t peer_addr_len = sizeof(struct sockaddr_storage); // variable that will contain the length of the peer's address
    
        ssize_t amount_read = recvfrom(sfd, buff, MAX_MESSAGE_SIZE, MSG_PEEK, (struct sockaddr *) &peer_addr, &peer_addr_len);
        if (amount_read == -1){ 
    
            return -1;
        }
    
        int err             = connect(sfd, (struct sockaddr *) &peer_addr, sizeof(struct sockaddr_storage));
    
        if (err != EISCONN && err != 0)
            return -1;
    
        char text[100];
        struct sockaddr_in6 * cast = (struct sockaddr_in6 *) &peer_addr;
        ipv6_to_str_unexpanded(text, &(cast->sin6_addr));
        DEBUG("Successfully connected to IPv6 addresss: %s, port : %d", text, ntohs(cast->sin6_port));
    
        return 0;
    
    unsigned long long int time_milliseconds(struct timeval *time)
    {
        return ((unsigned long long int) time->tv_sec * 1000) + ((unsigned long long int) time->tv_usec / 1000);
    }
    
    
    void write_stats_to_file(const char * pathname, transfer_stats_t * stats_file, agents_t caller)
    
        int fd = open(pathname, O_RDWR|O_CREAT|O_TRUNC, S_IRWXU);
    
        if (fd == -1)
        {
            // We can use strerror cause here the error is known since we are using standard library open
            DEBUG("%s", strerror(errno));
            return;
        }
    
        int ret = 0;
    
        ret = sprintf((char *) &buffer, "data_sent:%llu\n", stats_file->data_sent);
        ret = write(fd, buffer, strlen(buffer));
    
        ret = sprintf((char *) &buffer, "data_received:%llu\n", stats_file->data_received);
        ret = write(fd, buffer, strlen(buffer));
    
        ret = sprintf((char *) &buffer, "data_truncated_received:%llu\n", stats_file->data_truncated_received);
        ret = write(fd, buffer, strlen(buffer));
    
        ret = sprintf((char *) &buffer, "fec_sent:%llu\n", stats_file->fec_sent);
        ret = write(fd, buffer, strlen(buffer));
    
        ret = sprintf((char *) &buffer, "fec_received:%llu\n", stats_file->fec_received);
        ret = write(fd, buffer, strlen(buffer));
    
        ret = sprintf((char *) &buffer, "ack_sent:%llu\n", stats_file->ack_sent);
        ret = write(fd, buffer, strlen(buffer));
    
        ret = sprintf((char *) &buffer, "ack_received:%llu\n", stats_file->ack_received);
        ret = write(fd, buffer, strlen(buffer));
    
        ret = sprintf((char *) &buffer, "nack_received:%llu\n", stats_file->nack_received);
        ret = write(fd, buffer, strlen(buffer));
    
        ret = sprintf((char *) &buffer, "packet_ignored:%llu\n", stats_file->packet_ignored);
        ret = write(fd, buffer, strlen(buffer));
    
        if (caller == RECEIVER)
        {
            ret = sprintf((char *) &buffer, "packet_duplicated:%llu\n", stats_file->packet_duplicated);
            ret = write(fd, buffer, strlen(buffer));
    
            ret = sprintf((char *) &buffer, "packet_recovered:%llu\n", stats_file->packet_recovered);
            ret = write(fd, buffer, strlen(buffer));
        }
    
        if (caller == SENDER)
        {
    
            ret = sprintf((char *) &buffer, "min_rtt:%llu\n", stats_file->min_rtt);
    
            ret = write(fd, buffer, strlen(buffer));
    
            ret = sprintf((char *) &buffer, "max_rtt:%llu\n", stats_file->max_rtt);
    
            ret = write(fd, buffer, strlen(buffer));
    
            ret = sprintf((char *) &buffer, "packet_retransmitted:%llu\n", stats_file->packet_retransmitted);
            ret = write(fd, buffer, strlen(buffer));
        }    
        
    
        ret--; // dump
    
        DEBUG("Wrote the transfer statistics to %s.", pathname);
        return;