
#include <platform.h>

USING_NAMESPACE

NAMESPACE_BEGIN

const IP4addr ip4_anyaddr = {{0,0,0,0}};
const IP4addr ip4_loopback = {{127,0,0,1}};
const IP4addr ip4_loopback_net = {{127,0,0,0}};
const IP4addr ip4_multicast_net = {{224,0,0,0}};
const IP4addr ip4_multicast_all_router = {{224,0,0,2}};
const IP4addr ip4_class_a_mask = {{255,0,0,0}};
const IP4addr ip4_class_b_mask = {{255,255,0,0}};
const IP4addr ip4_class_c_mask = {{255,255,255,0}};
const IP4addr ip4_maskall = {{255,255,255,255}};

const Eaddr * mcast_eaddr(const IPaddr * addr)
{
    // 33-33-XX-XX-XX-XX + low-order 32 bits
    static Eaddr e;
    e.b[0] = 0x33;
    e.b[1] = 0x33;
    e.b[2] = addr->b[12];
    e.b[3] = addr->b[13];
    e.b[4] = addr->b[14];
    e.b[5] = addr->b[15];
    return &e;
}

const Eaddr bcast_eaddr = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
const Eaddr null_eaddr =  { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } };

/*---------------------------------------------------------------------------*/
/* objectIdentifier                                                          */
/*---------------------------------------------------------------------------*/

static void put_n(byte * & b, dword n)
{
    if( n < 0x80 ) goto _80;
    if( n < 0x4000 ) goto _4000;
    if( n < 0x200000 ) goto _200000;
    if( n < 0x10000000 ) goto _10000000;

    *b++ = (byte)(0x80 | ((n>>28) &0x7f));
_10000000:
    *b++ = (byte)(0x80 | ((n>>21) &0x7f));
_200000:
    *b++ = (byte)(0x80 | ((n>>14) &0x7f));
_4000:
    *b++ = (byte)(0x80 | ((n>>7) &0x7f));
_80:
    *b++ = (byte)(n &0x7f);
}

static dword get_n(byte * & b)
{
    dword n = 0;
    do {
        n<<=7;
        n |=(*b &0x7f);
    } while(*b++ &0x80);
    return n;
}

objectIdentifier::objectIdentifier()
{
    memset(b,0,sizeof(b));
}

objectIdentifier::objectIdentifier(byte * asn)
{
    if(asn) memcpy(b,asn,MIN(asn[0]+1, (int)sizeof(b)));
    else memset(b, 0, sizeof(b));
}

objectIdentifier::objectIdentifier(word len, ...)
{
    va_list ap;
    dword n;
    int i;
    byte * o = &b[1];

    va_start(ap,len);
    n = 40*va_arg(ap,dword);
    n += va_arg(ap,dword);
    put_n(o,n);
    for(i=2;i<len;i++) {
        put_n(o,va_arg(ap,dword));
    }
    va_end(ap);
    b[0] = (byte)(o-&b[1]);
}

byte objectIdentifier::len()
{
    return b[0];
}

byte * objectIdentifier::get()
{
    return b;
}

word objectIdentifier::get(dword * buffer)
{
    dword n;
    byte * o=&b[1];
    byte * l=&b[b[0]];

    n = get_n(o);
    buffer[0] = n/40;
    if(buffer[0]>2) buffer[0] = 2;
    buffer[1] = n-buffer[0]*40;
    for(n=2;o<=l;) buffer[n++] = get_n(o);
    return n;
}

word objectIdentifier::get(class objectIdentifier & base, word len, dword * buffer)
{
    if((b[0]<=base.b[0]) || memcmp(&b[1],&base.b[1],base.b[0])) return 0;

    dword n;
    byte * o;
    byte * l;

    o = &b[base.b[0]+1];
    l = &b[b[0]];
    for(n=0;o<=l && n<len;) buffer[n++] = get_n(o);
    return n;
}

void objectIdentifier::set(byte * asn)
{
    memcpy(b,asn,asn[0]+1);
}

void objectIdentifier::set(word len, ...)
{
    va_list ap;
    dword n;
    int i;
    byte * o = &b[1];
    
    va_start(ap,len);
    n = 40*va_arg(ap,dword);
    n += va_arg(ap,dword);
    put_n(o,n);
    for(i=2;i<len;i++) {
        put_n(o,va_arg(ap,dword));
    }
    va_end(ap);
    b[0] = (byte)(o-&b[1]);
}

void objectIdentifier::set(word len, dword * buffer)
{
    dword n;
    int i;
    byte * o = &b[1];

    n = 40*buffer[0];
    n += buffer[1];
    put_n(o,n);
    for(i=2;i<len;i++) {
        put_n(o,buffer[i]);
    }
    b[0] = (byte)(o-&b[1]);
}

void objectIdentifier::set(class objectIdentifier & base, word len, dword * buffer)
{
    memcpy(b,base.b,base.b[0]+1);

    int i;
    byte * o = &b[1+b[0]];

    for(i=0;i<len;i++) {
        put_n(o,buffer[i]);
    }
    b[0] = (byte)(o-&b[1]);
}

bool operator==(class objectIdentifier x, class objectIdentifier y)
{
    byte *xb = x.get();
    byte *yb = y.get();
    byte len = *xb + 1;

    while (len) {
        if (*xb != *yb)
            return false;

        xb++;
        yb++;
        len--;
    }

    return true;
}

NAMESPACE_END
