Make network connections work again on non-glibc systems

* lisp/net/gnutls.el (open-gnutls-stream): Pass the TLS
keywords in directly so that they can be used when doing
synchronous DNS on non-synchronous connections.

* lisp/net/network-stream.el (open-network-stream): Allow
passing in the TLS parameters directly.

* src/process.c (conv_numerical_to_lisp): New function to convert
numerical addresses to Lisp.
(Fmake_network_process): Rework the non-HAVE_ADDRINFO code
paths so that they work again.
(syms_of_process): Build fix for non-glibc systems.
This commit is contained in:
Lars Ingebrigtsen 2016-02-01 02:57:04 +01:00
parent 56cd5301f1
commit 0645c0f81b
3 changed files with 57 additions and 25 deletions

View file

@ -124,16 +124,16 @@ This is a very simple wrapper around `gnutls-negotiate'. See its
documentation for the specific parameters you can use to open a
GnuTLS connection, including specifying the credential type,
trust and key files, and priority string."
(let ((process (open-network-stream name buffer host service
:nowait nowait)))
(let ((process (open-network-stream
name buffer host service
:nowait nowait
:tls-parameters
(and nowait
(gnutls-negotiate :type 'gnutls-x509pki
:return-keywords t
:hostname host)))))
(if nowait
(progn
(gnutls-asynchronous-parameters
process
(gnutls-negotiate :type 'gnutls-x509pki
:return-keywords t
:hostname host))
process)
process
(gnutls-negotiate :process (open-network-stream name buffer host service)
:type 'gnutls-x509pki
:hostname host))))

View file

@ -137,7 +137,12 @@ non-nil, is used warn the user if the connection isn't encrypted.
a greeting from the server.
:nowait is a boolean that says the connection should be made
asynchronously, if possible."
asynchronously, if possible.
:tls-parameters is a list that should be supplied if you're
opening a TLS connection. The first element is the TLS type, and
the remaining elements should be a keyword list accepted by
gnutls-boot."
(unless (featurep 'make-network-process)
(error "Emacs was compiled without networking support"))
(let ((type (plist-get parameters :type))
@ -150,7 +155,9 @@ asynchronously, if possible."
;; The simplest case: wrapper around `make-network-process'.
(make-network-process :name name :buffer buffer
:host (puny-encode-domain host) :service service
:nowait (plist-get parameters :nowait))
:nowait (plist-get parameters :nowait)
:tls-parameters
(plist-get parameters :tls-parameters))
(let ((work-buffer (or buffer
(generate-new-buffer " *stream buffer*")))
(fun (cond ((and (eq type 'plain)

View file

@ -3303,12 +3303,13 @@ void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
set_network_socket_coding_system (proc);
#ifdef HAVE_GNUTLS
/* Continue the asynchronous connection. */
if (!NILP (p->gnutls_async_parameters) && p->is_non_blocking_client) {
Lisp_Object params = p->gnutls_async_parameters, boot = Qnil;
Lisp_Object boot, params = p->gnutls_async_parameters;
p->gnutls_async_parameters = Qnil;
p->gnutls_async_parameters = Qnil;
boot = Fgnutls_boot (proc, XCAR (params), XCDR (params));
if (STRINGP (boot)) {
if (NILP (boot) || STRINGP (boot)) {
pset_status (p, Qfailed);
deactivate_process (proc);
}
@ -3317,6 +3318,19 @@ void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
}
static Lisp_Object
conv_numerical_to_lisp (unsigned char *number, unsigned int length, int port)
{
Lisp_Object address = Fmake_vector (make_number (length + 1), Qnil);
register struct Lisp_Vector *p = XVECTOR (address);
int i;
p->contents[length] = make_number (port);
for (i = 0; i < length; i++)
p->contents[i] = make_number (*(number + i));
return address;
}
/* Create a network stream/datagram client/server process. Treated
exactly like a normal process when reading and writing. Primary
@ -3490,7 +3504,6 @@ usage: (make-network-process &rest ARGS) */)
struct sockaddr_un address_un;
#endif
int port = 0;
int ret = 0;
Lisp_Object tem;
Lisp_Object name, buffer, host, service, address;
Lisp_Object filter, sentinel;
@ -3661,6 +3674,8 @@ usage: (make-network-process &rest ARGS) */)
if (!NILP (Fplist_get (contact, QCnowait)) &&
!NILP (host))
{
int ret;
printf("Async DNS for '%s'\n", SSDATA (host));
dns_requests = xmalloc (sizeof (struct gaicb*));
dns_requests[0] = xmalloc (sizeof (struct gaicb));
@ -3724,7 +3739,7 @@ usage: (make-network-process &rest ARGS) */)
if (EQ (service, Qt))
port = 0;
else if (INTEGERP (service))
port = htons ((unsigned short) XINT (service));
port = (unsigned short) XINT (service);
else
{
struct servent *svc_info;
@ -3733,7 +3748,7 @@ usage: (make-network-process &rest ARGS) */)
(socktype == SOCK_DGRAM ? "udp" : "tcp"));
if (svc_info == 0)
error ("Unknown service: %s", SDATA (service));
port = svc_info->s_port;
port = ntohs (svc_info->s_port);
}
#ifndef HAVE_GETADDRINFO
@ -3750,24 +3765,29 @@ usage: (make-network-process &rest ARGS) */)
res_init ();
#endif
host_info_ptr = gethostbyname (SDATA (host));
host_info_ptr = gethostbyname ((const char *) SDATA (host));
immediate_quit = 0;
if (host_info_ptr)
{
ip_addresses = Ncons (make_number (host_info_ptr->h_addr,
host_info_ptr->h_length),
ip_addresses = Fcons (conv_numerical_to_lisp
((unsigned char *) host_info_ptr->h_addr,
host_info_ptr->h_length,
port),
Qnil);
}
else
/* Attempt to interpret host as numeric inet address. */
/* Attempt to interpret host as numeric inet address. This
only works for IPv4 addresses. */
{
unsigned long numeric_addr;
numeric_addr = inet_addr (SSDATA (host));
unsigned long numeric_addr = inet_addr (SSDATA (host));
if (numeric_addr == -1)
error ("Unknown host \"%s\"", SDATA (host));
ip_addresses = Ncons (make_number (numeric_addr), Qnil);
ip_addresses = Fcons (conv_numerical_to_lisp
((unsigned char *) &numeric_addr, 4, port),
Qnil);
}
}
@ -3802,7 +3822,9 @@ usage: (make-network-process &rest ARGS) */)
p->dns_requests = NULL;
#endif
#ifdef HAVE_GNUTLS
p->gnutls_async_parameters = Qnil;
tem = Fplist_get (contact, QCtls_parameters);
CHECK_LIST (tem);
p->gnutls_async_parameters = tem;
#endif
unbind_to (count, Qnil);
@ -7705,6 +7727,7 @@ syms_of_process (void)
DEFSYM (QCserver, ":server");
DEFSYM (QCnowait, ":nowait");
DEFSYM (QCsentinel, ":sentinel");
DEFSYM (QCtls_parameters, ":tls-parameters");
DEFSYM (QClog, ":log");
DEFSYM (QCnoquery, ":noquery");
DEFSYM (QCstop, ":stop");
@ -7719,7 +7742,9 @@ syms_of_process (void)
staticpro (&Vprocess_alist);
staticpro (&deleted_pid_list);
#ifdef HAVE_GETADDRINFO_A
staticpro (&dns_processes);
#endif
#endif /* subprocesses */