[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: :family extension for make_network_process
From: |
Kim F. Storm |
Subject: |
Re: :family extension for make_network_process |
Date: |
Fri, 16 Dec 2005 01:03:42 +0100 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) |
Kazu Yamamoto (山本和彦) <address@hidden> writes:
> Hello,
>
> From: address@hidden (Kim F. Storm)
> Subject: Re: :family extension for make_network_process
>
>> > I would report one documentation mistake and propose an extension for
>> > make_network_process.
>>
>> Does the following patch give good results?
>
> Yes. This code is much better than mine.
> Thanks!
It seems odd to only partially support IPv6, so here is a more
complete patch which adds an external representation of IPv6 addresses
(a 9 element vector -- 8 x 16-bit values for the address + 1 port number).
Can you pls. see if it makes sense.
BTW, with IPv4, it is custom to write 1.2.3.4:999 to separate the IP
address and port number. Is there a similar notation for IPv6?
I have used 1:2:3:4:5:6:7:8;999 in this patch for format-network-address
in lack of anything better....
*** process.c 01 Oct 2005 21:33:29 +0200 1.467
--- process.c 14 Dec 2005 16:42:54 +0100
***************
*** 140,146 ****
Lisp_Object Qprocessp;
Lisp_Object Qrun, Qstop, Qsignal;
Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
! Lisp_Object Qlocal, Qdatagram;
Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype;
Lisp_Object QClocal, QCremote, QCcoding;
Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
--- 140,149 ----
Lisp_Object Qprocessp;
Lisp_Object Qrun, Qstop, Qsignal;
Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
! Lisp_Object Qlocal, Qipv4, Qdatagram;
! #ifdef AF_INET6
! Lisp_Object Qipv6;
! #endif
Lisp_Object QCname, QCbuffer, QChost, QCservice, QCtype;
Lisp_Object QClocal, QCremote, QCcoding;
Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
***************
*** 1197,1203 ****
doc: /* Convert network ADDRESS from internal format to a string.
If optional second argument OMIT-PORT is non-nil, don't include a port
number in the string; in this case, interpret a 4 element vector as an
! IP address. Returns nil if format of ADDRESS is invalid. */)
(address, omit_port)
Lisp_Object address, omit_port;
{
--- 1200,1207 ----
doc: /* Convert network ADDRESS from internal format to a string.
If optional second argument OMIT-PORT is non-nil, don't include a port
number in the string; in this case, interpret a 4 element vector as an
! IPv4 address and an 8 element vector as an IPv6 address.
! Returns nil if format of ADDRESS is invalid. */)
(address, omit_port)
Lisp_Object address, omit_port;
{
***************
*** 1207,1213 ****
if (STRINGP (address)) /* AF_LOCAL */
return address;
! if (VECTORP (address)) /* AF_INET */
{
register struct Lisp_Vector *p = XVECTOR (address);
Lisp_Object args[6];
--- 1211,1217 ----
if (STRINGP (address)) /* AF_LOCAL */
return address;
! if (VECTORP (address)) /* AF_INET or AF_INET6 */
{
register struct Lisp_Vector *p = XVECTOR (address);
Lisp_Object args[6];
***************
*** 1223,1228 ****
--- 1227,1242 ----
args[0] = build_string ("%d.%d.%d.%d:%d");
nargs = 5;
}
+ else if (!NILP (omit_port) && (p->size == 8 || p->size == 9))
+ {
+ args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
+ nargs = 8;
+ }
+ else if (p->size == 9)
+ {
+ args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x;%d");
+ nargs = 9;
+ }
else
return Qnil;
***************
*** 2212,2217 ****
--- 2226,2244 ----
cp = (unsigned char *)&sin->sin_addr;
break;
}
+ #ifdef AF_INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ len = sizeof (sin6->sin6_addr)/2 + 1;
+ address = Fmake_vector (make_number (len), Qnil);
+ p = XVECTOR (address);
+ p->contents[--len] = make_number (ntohs (sin6->sin6_port));
+ for (i = 0; i < len; i++)
+ p->contents[i] = make_number (ntohs (sin6->sin6_addr.s6_addr16[i]));
+ return address;
+ }
+ #endif
#ifdef HAVE_LOCAL_SOCKETS
case AF_LOCAL:
{
***************
*** 2256,2261 ****
--- 2283,2295 ----
*familyp = AF_INET;
return sizeof (struct sockaddr_in);
}
+ #ifdef AF_INET6
+ else if (p->size == 9)
+ {
+ *familyp = AF_INET6;
+ return sizeof (struct sockaddr_in6);
+ }
+ #endif
}
#ifdef HAVE_LOCAL_SOCKETS
else if (STRINGP (address))
***************
*** 2302,2307 ****
--- 2336,2357 ----
sin->sin_port = htons (i);
cp = (unsigned char *)&sin->sin_addr;
}
+ #ifdef AF_INET6
+ else if (family == AF_INET6)
+ {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
+ len = sizeof (sin6->sin6_addr) + 1;
+ i = XINT (p->contents[--len]);
+ sin6->sin6_port = htons (i);
+ for (i = 0; i < len; i++)
+ if (INTEGERP (p->contents[i]))
+ {
+ int j = XFASTINT (p->contents[i]) & 0xffff;
+ sin6->sin6_addr.s6_addr16[i] = ntohs (j);
+ }
+ return;
+ }
+ #endif
}
else if (STRINGP (address))
{
***************
*** 2595,2604 ****
stream type connection, `datagram' creates a datagram type connection.
:family FAMILY -- FAMILY is the address (and protocol) family for the
! service specified by HOST and SERVICE. The default address family is
! Inet (or IPv4) for the host and port number specified by HOST and
! SERVICE. Other address families supported are:
local -- for a local (i.e. UNIX) address specified by SERVICE.
:local ADDRESS -- ADDRESS is the local address used for the connection.
This parameter is ignored when opening a client process. When specified
--- 2645,2657 ----
stream type connection, `datagram' creates a datagram type connection.
:family FAMILY -- FAMILY is the address (and protocol) family for the
! service specified by HOST and SERVICE. The default (nil) is to use
! whatever address family (IPv4 or IPv6) that is defined for the host
! and port number specified by HOST and SERVICE. Other address families
! supported are:
local -- for a local (i.e. UNIX) address specified by SERVICE.
+ ipv4 -- use IPv4 address family only.
+ ipv6 -- use IPv6 address family only.
:local ADDRESS -- ADDRESS is the local address used for the connection.
This parameter is ignored when opening a client process. When specified
***************
*** 2855,2873 ****
/* :family FAMILY -- nil (for Inet), local, or integer. */
tem = Fplist_get (contact, QCfamily);
! if (INTEGERP (tem))
! family = XINT (tem);
! else
{
! if (NILP (tem))
! family = AF_INET;
! #ifdef HAVE_LOCAL_SOCKETS
! else if (EQ (tem, Qlocal))
! family = AF_LOCAL;
#endif
}
! if (family < 0)
error ("Unknown address family");
ai.ai_family = family;
/* :service SERVICE -- string, integer (port number), or t (random port).
*/
--- 2908,2936 ----
/* :family FAMILY -- nil (for Inet), local, or integer. */
tem = Fplist_get (contact, QCfamily);
! if (NILP (tem))
{
! #ifdef HAVE_GETADDRINFO
! family = AF_UNSPEC;
! #else
! family = AF_INET;
#endif
}
! #ifdef HAVE_LOCAL_SOCKETS
! else if (EQ (tem, Qlocal))
! family = AF_LOCAL;
! #endif
! #ifdef AF_INET6
! else if (EQ (tem, Qipv6))
! family = AF_INET6;
! #endif
! else if (EQ (tem, Qipv4))
! family = AF_INET;
! else if (INTEGERP (tem))
! family = XINT (tem);
! else
error ("Unknown address family");
+
ai.ai_family = family;
/* :service SERVICE -- string, integer (port number), or t (random port).
*/
***************
*** 2933,2939 ****
QUIT;
memset (&hints, 0, sizeof (hints));
hints.ai_flags = 0;
! hints.ai_family = NILP (Fplist_member (contact, QCfamily)) ? AF_UNSPEC
: family;
hints.ai_socktype = socktype;
hints.ai_protocol = 0;
ret = getaddrinfo (SDATA (host), portstring, &hints, &res);
--- 2996,3002 ----
QUIT;
memset (&hints, 0, sizeof (hints));
hints.ai_flags = 0;
! hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = 0;
ret = getaddrinfo (SDATA (host), portstring, &hints, &res);
***************
*** 3816,3821 ****
--- 3879,3887 ----
union u_sockaddr {
struct sockaddr sa;
struct sockaddr_in in;
+ #ifdef AF_INET6
+ struct sockaddr_in6 in6;
+ #endif
#ifdef HAVE_LOCAL_SOCKETS
struct sockaddr_un un;
#endif
***************
*** 3872,3877 ****
--- 3938,3963 ----
}
break;
+ #ifdef AF_INET6
+ case AF_INET6:
+ {
+ Lisp_Object args[9];
+ uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr.s6_addr16;
+ int i;
+ args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
+ for (i = 0; i < 8; i++)
+ args[i+1] = make_number (ntohs(ip6[i]));
+ host = Fformat (9, args);
+ service = make_number (ntohs (saddr.in.sin_port));
+
+ args[0] = build_string (" <%s;%d>");
+ args[1] = host;
+ args[2] = service;
+ caller = Fformat (3, args);
+ }
+ break;
+ #endif
+
#ifdef HAVE_LOCAL_SOCKETS
case AF_LOCAL:
#endif
***************
*** 6724,6729 ****
--- 6810,6819 ----
#ifdef HAVE_LOCAL_SOCKETS
ADD_SUBFEATURE (QCfamily, Qlocal);
#endif
+ ADD_SUBFEATURE (QCfamily, Qipv4);
+ #ifdef AF_INET6
+ ADD_SUBFEATURE (QCfamily, Qipv6);
+ #endif
#ifdef HAVE_GETSOCKNAME
ADD_SUBFEATURE (QCservice, Qt);
#endif
***************
*** 6782,6787 ****
--- 6872,6883 ----
staticpro (&Qlisten);
Qlocal = intern ("local");
staticpro (&Qlocal);
+ Qipv4 = intern ("ipv4");
+ staticpro (&Qipv4);
+ #ifdef AF_INET6
+ Qipv6 = intern ("ipv6");
+ staticpro (&Qipv6);
+ #endif
Qdatagram = intern ("datagram");
staticpro (&Qdatagram);
--
Kim F. Storm <address@hidden> http://www.cua.dk