added partital socket address conversion routines to sck-addr.c
This commit is contained in:
parent
77942761f5
commit
4666b5efff
@ -378,9 +378,7 @@ class MyObject(Object)
|
||||
method(#class) main
|
||||
{
|
||||
| s conact inact outact |
|
||||
|
||||
|
||||
SocketAddress new dump.
|
||||
(SocketAddress fromString: '192.168.123.232:99') dump.
|
||||
'****************************' dump.
|
||||
|
||||
(*
|
||||
|
@ -736,7 +736,7 @@ int moo_convbtouchars (moo_t* moo, const moo_bch_t* bcs, moo_oow_t* bcslen, moo_
|
||||
if (n <= -1)
|
||||
{
|
||||
/* -1: illegal character, -2: buffer too small, -3: incomplete sequence */
|
||||
moo->errnum = (n == -2)? MOO_EBUFFULL: MOO_EECERR;
|
||||
moo_seterrnum (moo, (n == -2)? MOO_EBUFFULL: MOO_EECERR);
|
||||
}
|
||||
|
||||
return n;
|
||||
@ -751,7 +751,7 @@ int moo_convutobchars (moo_t* moo, const moo_uch_t* ucs, moo_oow_t* ucslen, moo_
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
moo->errnum = (n == -2)? MOO_EBUFFULL: MOO_EECERR;
|
||||
moo_seterrnum (moo, (n == -2)? MOO_EBUFFULL: MOO_EECERR);
|
||||
}
|
||||
|
||||
return n;
|
||||
@ -766,7 +766,7 @@ int moo_convbtoucstr (moo_t* moo, const moo_bch_t* bcs, moo_oow_t* bcslen, moo_u
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
moo->errnum = (n == -2)? MOO_EBUFFULL: MOO_EECERR;
|
||||
moo_seterrnum (moo, (n == -2)? MOO_EBUFFULL: MOO_EECERR);
|
||||
}
|
||||
|
||||
return n;
|
||||
@ -781,7 +781,7 @@ int moo_convutobcstr (moo_t* moo, const moo_uch_t* ucs, moo_oow_t* ucslen, moo_b
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
moo->errnum = (n == -2)? MOO_EBUFFULL: MOO_EECERR;
|
||||
moo_seterrnum (moo, (n == -2)? MOO_EBUFFULL: MOO_EECERR);
|
||||
}
|
||||
|
||||
return n;
|
||||
@ -931,3 +931,74 @@ moo_bch_t* moo_dupbchars (moo_t* moo, const moo_bch_t* bcs, moo_oow_t bcslen)
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#if defined(MOO_HAVE_UINT16_T)
|
||||
|
||||
moo_uint16_t moo_ntoh16 (moo_uint16_t x)
|
||||
{
|
||||
#if defined(MOO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MOO_ENDIAN_LITTLE)
|
||||
moo_uint8_t* c = (moo_uint8_t*)&x;
|
||||
return (moo_uint16_t)(
|
||||
((moo_uint16_t)c[0] << 8) |
|
||||
((moo_uint16_t)c[1] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
moo_uint16_t moo_hton16 (moo_uint16_t x)
|
||||
{
|
||||
#if defined(MOO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MOO_ENDIAN_LITTLE)
|
||||
moo_uint8_t* c = (moo_uint8_t*)&x;
|
||||
return (moo_uint16_t)(
|
||||
((moo_uint16_t)c[0] << 8) |
|
||||
((moo_uint16_t)c[1] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------- */
|
||||
|
||||
#if defined(MOO_HAVE_UINT32_T)
|
||||
|
||||
moo_uint32_t moo_ntoh32 (moo_uint32_t x)
|
||||
{
|
||||
#if defined(MOO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MOO_ENDIAN_LITTLE)
|
||||
moo_uint8_t* c = (moo_uint8_t*)&x;
|
||||
return (moo_uint32_t)(
|
||||
((moo_uint32_t)c[0] << 24) |
|
||||
((moo_uint32_t)c[1] << 16) |
|
||||
((moo_uint32_t)c[2] << 8) |
|
||||
((moo_uint32_t)c[3] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
|
||||
moo_uint32_t moo_hton32 (moo_uint32_t x)
|
||||
{
|
||||
#if defined(MOO_ENDIAN_BIG)
|
||||
return x;
|
||||
#elif defined(MOO_ENDIAN_LITTLE)
|
||||
moo_uint8_t* c = (moo_uint8_t*)&x;
|
||||
return (moo_uint32_t)(
|
||||
((moo_uint32_t)c[0] << 24) |
|
||||
((moo_uint32_t)c[1] << 16) |
|
||||
((moo_uint32_t)c[2] << 8) |
|
||||
((moo_uint32_t)c[3] << 0));
|
||||
#else
|
||||
# error Unknown endian
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
@ -100,20 +100,396 @@ union sockaddr_t
|
||||
};
|
||||
typedef union sockaddr_t sockaddr_t;
|
||||
|
||||
static int str_to_ipv4 (const moo_ooch_t* str, moo_oow_t len, struct in_addr* inaddr)
|
||||
{
|
||||
const moo_ooch_t* end;
|
||||
int dots = 0, digits = 0;
|
||||
moo_uint32_t acc = 0, addr = 0;
|
||||
moo_ooch_t c;
|
||||
|
||||
end = str + len;
|
||||
|
||||
do
|
||||
{
|
||||
if (str >= end)
|
||||
{
|
||||
if (dots < 3 || digits == 0) return -1;
|
||||
addr = (addr << 8) | acc;
|
||||
break;
|
||||
}
|
||||
|
||||
c = *str++;
|
||||
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
if (digits > 0 && acc == 0) return -1;
|
||||
acc = acc * 10 + (c - '0');
|
||||
if (acc > 255) return -1;
|
||||
digits++;
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
if (dots >= 3 || digits == 0) return -1;
|
||||
addr = (addr << 8) | acc;
|
||||
dots++; acc = 0; digits = 0;
|
||||
}
|
||||
else return -1;
|
||||
}
|
||||
while (1);
|
||||
|
||||
inaddr->s_addr = moo_hton32(addr);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int str_to_ipv6 (const moo_ooch_t* src, moo_oow_t len, struct in6_addr* inaddr)
|
||||
{
|
||||
moo_uint8_t* tp, * endp, * colonp;
|
||||
const moo_ooch_t* curtok;
|
||||
moo_ooch_t ch;
|
||||
int saw_xdigit;
|
||||
unsigned int val;
|
||||
const moo_ooch_t* src_end;
|
||||
|
||||
src_end = src + len;
|
||||
|
||||
MOO_MEMSET (inaddr, 0, MOO_SIZEOF(*inaddr));
|
||||
tp = &inaddr->s6_addr[0];
|
||||
endp = &inaddr->s6_addr[MOO_COUNTOF(inaddr->s6_addr)];
|
||||
colonp = MOO_NULL;
|
||||
|
||||
/* Leading :: requires some special handling. */
|
||||
if (src < src_end && *src == ':')
|
||||
{
|
||||
src++;
|
||||
if (src >= src_end || *src != ':') return -1;
|
||||
}
|
||||
|
||||
curtok = src;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
|
||||
while (src < src_end)
|
||||
{
|
||||
int v1;
|
||||
|
||||
ch = *src++;
|
||||
|
||||
if (ch >= '0' && ch <= '9')
|
||||
v1 = ch - '0';
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
v1 = ch - 'A' + 10;
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
v1 = ch - 'a' + 10;
|
||||
else v1 = -1;
|
||||
if (v1 >= 0)
|
||||
{
|
||||
val <<= 4;
|
||||
val |= v1;
|
||||
if (val > 0xffff) return -1;
|
||||
saw_xdigit = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == ':')
|
||||
{
|
||||
curtok = src;
|
||||
if (!saw_xdigit)
|
||||
{
|
||||
if (colonp) return -1;
|
||||
colonp = tp;
|
||||
continue;
|
||||
}
|
||||
else if (src >= src_end)
|
||||
{
|
||||
/* a colon can't be the last character */
|
||||
return -1;
|
||||
}
|
||||
|
||||
*tp++ = (moo_uint8_t)(val >> 8) & 0xff;
|
||||
*tp++ = (moo_uint8_t)val & 0xff;
|
||||
saw_xdigit = 0;
|
||||
val = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '.' && ((tp + MOO_SIZEOF(struct in_addr)) <= endp) &&
|
||||
str_to_ipv4(curtok, src_end - curtok, (struct in_addr*)tp) == 0)
|
||||
{
|
||||
tp += MOO_SIZEOF(struct in_addr*);
|
||||
saw_xdigit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (saw_xdigit)
|
||||
{
|
||||
if (tp + MOO_SIZEOF(moo_uint16_t) > endp) return -1;
|
||||
*tp++ = (moo_uint8_t)(val >> 8) & 0xff;
|
||||
*tp++ = (moo_uint8_t)val & 0xff;
|
||||
}
|
||||
if (colonp != MOO_NULL)
|
||||
{
|
||||
/*
|
||||
* Since some memmove()'s erroneously fail to handle
|
||||
* overlapping regions, we'll do the shift by hand.
|
||||
*/
|
||||
moo_oow_t n = tp - colonp;
|
||||
moo_oow_t i;
|
||||
|
||||
for (i = 1; i <= n; i++)
|
||||
{
|
||||
endp[-i] = colonp[n - i];
|
||||
colonp[n - i] = 0;
|
||||
}
|
||||
tp = endp;
|
||||
}
|
||||
|
||||
if (tp != endp) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int str_to_sockaddr (moo_t* moo, const moo_ooch_t* str, moo_oow_t len, sockaddr_t* nwad)
|
||||
{
|
||||
const moo_ooch_t* p;
|
||||
const moo_ooch_t* end;
|
||||
moo_oocs_t tmp;
|
||||
|
||||
p = str;
|
||||
end = str + len;
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "blank address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
MOO_MEMSET (nwad, 0, MOO_SIZEOF(*nwad));
|
||||
|
||||
#if defined(AF_UNIX)
|
||||
if (*p == '/' && len >= 2)
|
||||
{
|
||||
#if defined(MOO_OOCH_IS_BCH)
|
||||
moo_copybcstr (nwad->un.sun_path, MOO_COUNTOF(nwad->un.sun_path), str);
|
||||
#else
|
||||
moo_oow_t dstlen;
|
||||
|
||||
dstlen = MOO_COUNTOF(nwad->un.sun_path) - 1;
|
||||
if (moo_convutobchars (moo, p, &len, nwad->un.sun_path, &dstlen) <= -1)
|
||||
{
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "unable to convert encoding");
|
||||
return -1;
|
||||
}
|
||||
nwad->un.sun_path[dstlen] = '\0';
|
||||
#endif
|
||||
nwad->un.sun_family = AF_UNIX;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (*p == '[')
|
||||
{
|
||||
/* IPv6 address */
|
||||
tmp.ptr = (moo_ooch_t*)++p; /* skip [ and remember the position */
|
||||
while (p < end && *p != '%' && *p != ']') p++;
|
||||
|
||||
if (p >= end) goto norbrack;
|
||||
|
||||
tmp.len = p - tmp.ptr;
|
||||
if (*p == '%')
|
||||
{
|
||||
/* handle scope id */
|
||||
moo_uint32_t x;
|
||||
|
||||
p++; /* skip % */
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
/* premature end */
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "scope id blank");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p >= '0' && *p <= '9')
|
||||
{
|
||||
/* numeric scope id */
|
||||
nwad->in6.sin6_scope_id = 0;
|
||||
do
|
||||
{
|
||||
x = nwad->in6.sin6_scope_id * 10 + (*p - '0');
|
||||
if (x < nwad->in6.sin6_scope_id)
|
||||
{
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "scope id too large");
|
||||
return -1; /* overflow */
|
||||
}
|
||||
nwad->in6.sin6_scope_id = x;
|
||||
p++;
|
||||
}
|
||||
while (p < end && *p >= '0' && *p <= '9');
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
TODO:
|
||||
/* interface name as a scope id? */
|
||||
const moo_ooch_t* stmp = p;
|
||||
unsigned int index;
|
||||
do p++; while (p < end && *p != ']');
|
||||
if (moo_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
||||
tmpad.u.in6.scope = index;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (p >= end || *p != ']') goto norbrack;
|
||||
}
|
||||
p++; /* skip ] */
|
||||
|
||||
if (str_to_ipv6(tmp.ptr, tmp.len, &nwad->in6.sin6_addr) <= -1) goto unrecog;
|
||||
nwad->in6.sin6_family = AF_INET6;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* IPv4 address */
|
||||
tmp.ptr = (moo_ooch_t*)p;
|
||||
while (p < end && *p != ':') p++;
|
||||
tmp.len = p - tmp.ptr;
|
||||
|
||||
if (str_to_ipv4(tmp.ptr, tmp.len, &nwad->in4.sin_addr) <= -1)
|
||||
{
|
||||
/* check if it is an IPv6 address not enclosed in [].
|
||||
* the port number can't be specified in this format. */
|
||||
if (p >= end || *p != ':')
|
||||
{
|
||||
/* without :, it can't be an ipv6 address */
|
||||
goto unrecog;
|
||||
}
|
||||
|
||||
|
||||
while (p < end && *p != '%') p++;
|
||||
tmp.len = p - tmp.ptr;
|
||||
|
||||
if (str_to_ipv6(tmp.ptr, tmp.len, &nwad->in6.sin6_addr) <= -1) goto unrecog;
|
||||
|
||||
if (p < end && *p == '%')
|
||||
{
|
||||
/* handle scope id */
|
||||
moo_uint32_t x;
|
||||
|
||||
p++; /* skip % */
|
||||
|
||||
if (p >= end)
|
||||
{
|
||||
/* premature end */
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "scope id blank");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*p >= '0' && *p <= '9')
|
||||
{
|
||||
/* numeric scope id */
|
||||
nwad->in6.sin6_scope_id = 0;
|
||||
do
|
||||
{
|
||||
x = nwad->in6.sin6_scope_id * 10 + (*p - '0');
|
||||
if (x < nwad->in6.sin6_scope_id)
|
||||
{
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "scope id too large");
|
||||
return -1; /* overflow */
|
||||
}
|
||||
nwad->in6.sin6_scope_id= x;
|
||||
p++;
|
||||
}
|
||||
while (p < end && *p >= '0' && *p <= '9');
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
TODO
|
||||
/* interface name as a scope id? */
|
||||
const moo_ooch_t* stmp = p;
|
||||
unsigned int index;
|
||||
do p++; while (p < end);
|
||||
if (moo_nwifwcsntoindex (stmp, p - stmp, &index) <= -1) return -1;
|
||||
nwad->in6.sin6_scope_id = index;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (p < end) goto unrecog; /* some gargage after the end? */
|
||||
|
||||
nwad->in6.sin6_family = AF_INET6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
nwad->in4.sin_family = AF_INET;
|
||||
}
|
||||
|
||||
if (p < end && *p == ':')
|
||||
{
|
||||
/* port number */
|
||||
moo_uint32_t port = 0;
|
||||
|
||||
p++; /* skip : */
|
||||
|
||||
tmp.ptr = (moo_ooch_t*)p;
|
||||
while (p < end && *p >= '0' && *p <= '9')
|
||||
{
|
||||
port = port * 10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
|
||||
tmp.len = p - tmp.ptr;
|
||||
if (tmp.len <= 0 || tmp.len >= 6 ||
|
||||
port > MOO_TYPE_MAX(moo_uint16_t))
|
||||
{
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "port number blank or too large");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nwad->in4.sin_family == AF_INET)
|
||||
nwad->in4.sin_port = moo_hton16(port);
|
||||
else
|
||||
nwad->in6.sin6_port = moo_hton16(port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
unrecog:
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "unrecognized address");
|
||||
return -1;
|
||||
|
||||
norbrack:
|
||||
moo_seterrbfmt (moo, MOO_EINVAL, "missing right bracket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static moo_pfrc_t pf_from_string (moo_t* moo, moo_ooi_t nargs)
|
||||
{
|
||||
moo_oop_t rcv;
|
||||
sck_addr_trailer_t* tr;
|
||||
moo_oop_t str;
|
||||
|
||||
rcv = (moo_oop_t)MOO_STACK_GETRCV(moo, nargs);
|
||||
str = (moo_oop_t)MOO_STACK_GETARG(moo, nargs, 0);
|
||||
|
||||
tr = moo_getobjtrailer (moo, MOO_STACK_GETRCV(moo,nargs), MOO_NULL);
|
||||
//if (tr->event)
|
||||
MOO_PF_CHECK_RCV (moo, MOO_OBJ_IS_BYTE_POINTER(rcv) && MOO_OBJ_GET_SIZE(rcv) >= MOO_SIZEOF(sockaddr_t));
|
||||
MOO_PF_CHECK_ARGS (moo, nargs, MOO_OBJ_IS_CHAR_POINTER(str));
|
||||
|
||||
if (str_to_sockaddr (moo, MOO_OBJ_GET_CHAR_SLOT(str), MOO_OBJ_GET_SIZE(str), (sockaddr_t*)MOO_OBJ_GET_BYTE_SLOT(rcv)) <= -1)
|
||||
{
|
||||
return MOO_PF_FAILURE;
|
||||
}
|
||||
|
||||
MOO_STACK_SETRETTORCV (moo, nargs);
|
||||
return MOO_PF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static moo_pfinfo_t pfinfos[] =
|
||||
{
|
||||
{ I, { 'f','r','o','m','S','t','r','i','n','g',':','\0' }, 0, { pf_from_string, 1, 1 } },
|
||||
@ -121,8 +497,6 @@ static moo_pfinfo_t pfinfos[] =
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
|
||||
static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
|
||||
{
|
||||
moo_ooi_t spec;
|
||||
@ -135,9 +509,9 @@ static int import (moo_t* moo, moo_mod_t* mod, moo_oop_class_t _class)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* change the number of the fixed fields forcibly */
|
||||
/* TODO: check if the super class has what kind of size ... */
|
||||
|
||||
/* change the number of the fixed fields forcibly.
|
||||
/* the check against the superclass is done by the main compiler
|
||||
* after this import. so i perform no check about the superclass. */
|
||||
spec = MOO_CLASS_SPEC_MAKE (MOO_SIZEOF(sockaddr_t), MOO_CLASS_SPEC_FLAGS(spec), MOO_CLASS_SPEC_INDEXED_TYPE(spec));
|
||||
_class->spec = MOO_SMOOI_TO_OOP(spec);
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user