#include "encode.hpp"
#include <stdlib.h>
#include <sys/time.h>


void to_hex(const unsigned char* from, unsigned char* to, size_t len) {
    while (len) {
        sprintf((char*)to, "%02x", (unsigned char)*from);
        len--;
        from++;
        to += 2;
    }
}


bool from_hex(const unsigned char* from, unsigned char* to, size_t len) {
    if (len % 2 != 0) {
        return false;
    }
    while (len) {
        unsigned h;
        if (sscanf((const char*)from, "%02x", &h) != 1) {
            return false;
        }
        *to = (unsigned char)h;
        len -= 2;
        from += 2;
        to++;
    }
    return true;
}


static uint64_t htonll(uint64_t v) {
    uint32_t hi = htonl((uint32_t)(v >> 32));
    uint32_t lo = htonl((uint32_t)(v & 0xffffffffllu));
    return (((uint64_t)lo) << 32) | hi;
}


uint64_t get_nonce() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    srand(tv.tv_usec);

    union {
        uint64_t a;
        uint16_t b[4];
    } rv;
    rv.b[0] = (uint16_t)rand(); // TODO: this is not sound
    rv.b[1] = (uint16_t)rand();
    rv.b[2] = (uint16_t)rand();
    rv.b[3] = (uint16_t)rand();
    return rv.a;
}


uint64_t obfuscate_dst(uint64_t nonce, const sockaddr_in& dst) {
    static const uint64_t secret = htonll(0xabcdefabcdefabcdllu);
    static const uint16_t sentinel = htons(0xb3e4);
    union {
        uint64_t v;
        struct {
            uint16_t sentinel;
            uint16_t port;
            uint32_t addr;
        };
    } d;
    d.sentinel = sentinel;
    d.port = dst.sin_port;
    d.addr = dst.sin_addr.s_addr;
    return (d.v ^ secret) ^ nonce;
}