Files
unison/src/common/utils.cc
Mathieu Lacage 5c90e561b4 import from yans
2006-08-29 17:42:13 +02:00

294 lines
7.2 KiB
C++

/* -*- Mode:C++; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
/*
* Copyright (c) 2005 INRIA
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "utils.h"
namespace yans {
uint16_t
utils_hton_16 (uint16_t v)
{
uint8_t array[2];
array[0] = (v >> 8) & 0xff;
array[1] = (v >> 0) & 0xff;
return *((uint16_t *)array);
}
uint32_t
utils_hton_32 (uint32_t v)
{
uint8_t array[4];
array[0] = (v >> 24) & 0xff;
array[1] = (v >> 16) & 0xff;
array[2] = (v >> 8) & 0xff;
array[3] = (v >> 0) & 0xff;
return *((uint32_t *)array);
}
uint16_t
utils_ntoh_16 (uint16_t v)
{
uint16_t val;
uint8_t *array;
array = (uint8_t *)&v;
val = (array[0] << 8) | (array[1] << 0);
return val;
}
uint32_t
utils_ntoh_32 (uint32_t v)
{
uint32_t val = 0;
uint8_t *array = (uint8_t *)&v;
val |= array[0] << 24;
val |= array[1] << 16;
val |= array[2] << 8;
val |= array[3] << 0;
return val;
}
#define ASCII_DOT (0x2e)
#define ASCII_ZERO (0x30)
#define ASCII_A (0x41)
#define ASCII_Z (0x5a)
#define ASCII_a (0x61)
#define ASCII_z (0x7a)
#define ASCII_COLON (0x3a)
uint32_t
ascii_to_ipv4_host (char const *address)
{
uint32_t host = 0;
while (true) {
uint8_t byte = 0;
while (*address != ASCII_DOT &&
*address != 0) {
byte *= 10;
byte += *address - ASCII_ZERO;
address++;
}
host <<= 8;
host |= byte;
if (*address == 0) {
break;
}
address++;
}
return host;
}
char
ascii_to_low_case (char c)
{
if (c >= ASCII_a && c <= ASCII_z) {
return c;
} else if (c >= ASCII_A && c <= ASCII_Z) {
return c + (ASCII_a - ASCII_A);
} else {
return c;
}
}
void
ascii_to_mac_network (char const *str, uint8_t address[6])
{
uint8_t i = 0;
while (*str != 0 && i < 6) {
uint8_t byte = 0;
while (*str != ASCII_COLON && *str != 0) {
byte <<= 4;
char low = ascii_to_low_case (*str);
if (low >= ASCII_a) {
byte |= low - ASCII_a + 10;
} else {
byte |= low - ASCII_ZERO;
}
str++;
}
address[i] = byte;
str++;
i++;
}
}
uint16_t
utils_checksum_calculate (uint16_t checksum, uint8_t *buffer, uint16_t size)
{
/* see RFC 1071 to understand this code. */
uint32_t sum = checksum;
uint16_t *data = (uint16_t *) buffer;
for (uint16_t i = 0; i < (size/2); i++) {
sum += data[i];
}
if ((size % 2) != 0) {
uint8_t tmp_buf[2];
tmp_buf[0] = buffer[size-1];
tmp_buf[1] = 0;
data = (uint16_t *)tmp_buf;
sum += *data;
}
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
}
return sum;
}
uint16_t
utils_checksum_complete (uint16_t checksum)
{
return ~checksum;
}
}; // namespace yans
#ifdef RUN_SELF_TESTS
#include "yans/test.h"
namespace yans {
class UtilsTest : public Test {
public:
UtilsTest ();
virtual bool run_tests (void);
private:
bool test_ipv4_ascii_to_host (char const *str, uint32_t expected);
bool test_mac_ascii (char const *str, uint8_t expected[6]);
bool test_hton_16 (uint16_t v, uint8_t expected[2]);
};
bool
UtilsTest::test_ipv4_ascii_to_host (char const *str, uint32_t expected)
{
if (ascii_to_ipv4_host (str) != expected) {
failure () << "Utils ascii to host --"
<< " for: \"" << str << "\""
<< " expected: " << expected
<< " got: " << ascii_to_ipv4_host (str)
<< std::endl;
return false;
}
return true;
}
bool
UtilsTest::test_mac_ascii (char const *str, uint8_t expected[6])
{
uint8_t got[6];
ascii_to_mac_network (str, got);
for (uint8_t i = 0; i < 6; i++) {
if (got[i] != expected[i]) {
failure () << "Utils ascii to mac --"
<< " for: \"" << str << "\""
<< " expected: ";
failure ().setf (std::ios::hex, std::ios::basefield);
failure () << (uint32_t)expected[0] << ":"
<< (uint32_t)expected[1] << ":"
<< (uint32_t)expected[2] << ":"
<< (uint32_t)expected[3] << ":"
<< (uint32_t)expected[4] << ":"
<< (uint32_t)expected[5];
failure ().setf (std::ios::dec, std::ios::basefield);
failure () << " got: ";
failure ().setf (std::ios::hex, std::ios::basefield);
failure () << (uint32_t)got[0] << ":"
<< (uint32_t)got[1] << ":"
<< (uint32_t)got[2] << ":"
<< (uint32_t)got[3] << ":"
<< (uint32_t)got[4] << ":"
<< (uint32_t)got[5];
failure ().setf (std::ios::dec, std::ios::basefield);
failure () << std::endl;
return false;
}
}
return true;
}
bool
UtilsTest::test_hton_16 (uint16_t v, uint8_t expected[2])
{
uint16_t result = utils_hton_16 (v);
uint8_t *got = (uint8_t *)&result;
if (got[0] != expected[0] ||
got[1] != expected[1]) {
failure () << "Utils hton 16 --"
<< " for: \"" << v << "\""
<< " expected: ";
failure ().setf (std::ios::hex, std::ios::basefield);
failure () << (uint32_t)expected[0] << ":"
<< (uint32_t)expected[1];
failure () << " got: ";
failure () << (uint32_t)got[0] << ":"
<< (uint32_t)got[1];
failure ().setf (std::ios::dec, std::ios::basefield);
failure () << std::endl;
return false;
}
return true;
}
#define TEST_IPV4_ASCII_TO_HOST(a,b) \
if (!test_ipv4_ascii_to_host (a,b)) { \
ok = false; \
}
#define TEST_MAC_ASCII(ad, a, b, c, d, e, f) \
{ \
uint8_t expected[6] = {a, b, c, d, e, f}; \
if (!test_mac_ascii (ad, expected)) { \
ok = false; \
} \
}
#define TEST_HTON_16(v, a, b) \
{ \
uint8_t expected[2] = {a, b}; \
if (!test_hton_16 (v, expected)) { \
ok = false; \
} \
}
UtilsTest::UtilsTest ()
: Test ("Utils") {}
bool
UtilsTest::run_tests (void)
{
bool ok = true;
TEST_IPV4_ASCII_TO_HOST ("255.255.255.255", 0xffffffff);
TEST_IPV4_ASCII_TO_HOST ("255.255.255.0", 0xffffff00);
TEST_IPV4_ASCII_TO_HOST ("255.255.255.00", 0xffffff00);
TEST_IPV4_ASCII_TO_HOST ("255.255.255.000", 0xffffff00);
TEST_IPV4_ASCII_TO_HOST ("255.255.255.0000", 0xffffff00);
TEST_IPV4_ASCII_TO_HOST ("255.255.0.255", 0xffff00ff);
TEST_IPV4_ASCII_TO_HOST ("192.168.0.1", 0xc0a80001);
TEST_IPV4_ASCII_TO_HOST ("0.168.0.1", 0x00a80001);
TEST_MAC_ASCII ("00:00:00:00:00:00", 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
TEST_MAC_ASCII ("00:00:00:00:00:01", 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
TEST_MAC_ASCII ("01:00:00:00:00:01", 0x01, 0x00, 0x00, 0x00, 0x00, 0x01);
TEST_MAC_ASCII ("ff:00:00:ff:00:01", 0xff, 0x00, 0x00, 0xff, 0x00, 0x01);
TEST_MAC_ASCII ("f0:00:00:00:5d:01", 0xf0, 0x00, 0x00, 0x00, 0x5d, 0x01);
TEST_HTON_16 (0xf00f, 0xf0, 0x0f);
return ok;
}
static UtilsTest g_utils_test;
}; //namespace yans
#endif /* RUN_SELF_TESTS */