/* Indexed by descriptor, gives the process (if any) for that descriptor. */
static Lisp_Object chan_process[FD_SETSIZE];
+#ifdef HAVE_GETADDRINFO_A
+/* Pending DNS requests. */
+static Lisp_Object dns_processes;
+static void wait_for_socket_fds (Lisp_Object process, char *name);
+#endif
/* Alist of elements (NAME . PROCESS). */
static Lisp_Object Vprocess_alist;
p->sentinel = NILP (val) ? Qinternal_default_process_sentinel : val;
}
static void
-pset_status (struct Lisp_Process *p, Lisp_Object val)
-{
- p->status = val;
-}
-static void
pset_tty_name (struct Lisp_Process *p, Lisp_Object val)
{
p->tty_name = val;
#ifdef HAVE_GNUTLS
p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
+ p->gnutls_boot_parameters = Qnil;
#endif
/* If name is already in use, modify it until it is unused. */
struct Lisp_Process *p;
CHECK_PROCESS (process);
+
p = XPROCESS (process);
/* Don't signal an error if the process's input file descriptor
CHECK_RANGED_INTEGER (height, 0, USHRT_MAX);
CHECK_RANGED_INTEGER (width, 0, USHRT_MAX);
- if (XPROCESS (process)->infd < 0
+ if (NETCONN_P (process)
+ || XPROCESS (process)->infd < 0
|| (set_window_size (XPROCESS (process)->infd,
XINT (height), XINT (width))
< 0))
contact = XPROCESS (process)->childp;
#ifdef DATAGRAM_SOCKETS
+
+ if (NETCONN_P (process))
+ wait_for_socket_fds (process, "process-contact");
+
if (DATAGRAM_CONN_P (process)
&& (EQ (key, Qt) || EQ (key, QCremote)))
contact = Fplist_put (contact, QCremote,
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa;
uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr;
- len = sizeof (sin6->sin6_addr) + 1;
+ len = sizeof (sin6->sin6_addr) / 2 + 1;
hostport = XINT (p->contents[--len]);
sin6->sin6_port = htons (hostport);
for (i = 0; i < len; i++)
CHECK_PROCESS (process);
+ if (NETCONN_P (process))
+ wait_for_socket_fds (process, "process-datagram-address");
+
if (!DATAGRAM_CONN_P (process))
return Qnil;
CHECK_PROCESS (process);
+ if (NETCONN_P (process))
+ wait_for_socket_fds (process, "set-process-datagram-address");
+
if (!DATAGRAM_CONN_P (process))
return Qnil;
if (!NETCONN1_P (p))
error ("Process is not a network process");
+ wait_for_socket_fds (process, "set-network-process-option");
+
s = p->infd;
if (s < 0)
error ("Process is not running");
return proc;
}
-void set_network_socket_coding_system (Lisp_Object proc) {
+void set_network_socket_coding_system (Lisp_Object proc)
+{
Lisp_Object tem;
struct Lisp_Process *p = XPROCESS (proc);
Lisp_Object contact = p->childp;
Lisp_Object service, host, name;
+ Lisp_Object coding_systems = Qt;
+ Lisp_Object val;
service = Fplist_get (contact, QCservice);
host = Fplist_get (contact, QChost);
if (!NILP (tem) && (!CONSP (tem) || !CONSP (XCDR (tem))))
tem = Qnil; /* No error message (too late!). */
- {
- /* Setup coding systems for communicating with the network stream. */
- /* Qt denotes we have not yet called Ffind_operation_coding_system. */
- Lisp_Object coding_systems = Qt;
- Lisp_Object val;
+ /* Setup coding systems for communicating with the network stream. */
+ /* Qt denotes we have not yet called Ffind_operation_coding_system. */
- if (!NILP (tem))
- {
- val = XCAR (XCDR (tem));
- if (CONSP (val))
- val = XCAR (val);
- }
- else if (!NILP (Vcoding_system_for_read))
- val = Vcoding_system_for_read;
- else if ((!NILP (p->buffer) &&
- NILP (BVAR (XBUFFER (p->buffer), enable_multibyte_characters)))
- || (NILP (p->buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
- /* We dare not decode end-of-line format by setting VAL to
- Qraw_text, because the existing Emacs Lisp libraries
- assume that they receive bare code including a sequence of
- CR LF. */
- val = Qnil;
- else
- {
- if (NILP (host) || NILP (service))
- coding_systems = Qnil;
- else
- coding_systems = CALLN (Ffind_operation_coding_system,
- Qopen_network_stream, name, p->buffer,
- host, service);
- if (CONSP (coding_systems))
- val = XCAR (coding_systems);
- else if (CONSP (Vdefault_process_coding_system))
- val = XCAR (Vdefault_process_coding_system);
- else
- val = Qnil;
- }
- pset_decode_coding_system (p, val);
+ if (!NILP (tem))
+ {
+ val = XCAR (XCDR (tem));
+ if (CONSP (val))
+ val = XCAR (val);
+ }
+ else if (!NILP (Vcoding_system_for_read))
+ val = Vcoding_system_for_read;
+ else if ((!NILP (p->buffer) &&
+ NILP (BVAR (XBUFFER (p->buffer), enable_multibyte_characters)))
+ || (NILP (p->buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
+ /* We dare not decode end-of-line format by setting VAL to
+ Qraw_text, because the existing Emacs Lisp libraries
+ assume that they receive bare code including a sequence of
+ CR LF. */
+ val = Qnil;
+ else
+ {
+ if (NILP (host) || NILP (service))
+ coding_systems = Qnil;
+ else
+ coding_systems = CALLN (Ffind_operation_coding_system,
+ Qopen_network_stream, name, p->buffer,
+ host, service);
+ if (CONSP (coding_systems))
+ val = XCAR (coding_systems);
+ else if (CONSP (Vdefault_process_coding_system))
+ val = XCAR (Vdefault_process_coding_system);
+ else
+ val = Qnil;
+ }
+ pset_decode_coding_system (p, val);
- if (!NILP (tem))
- {
- val = XCAR (XCDR (tem));
- if (CONSP (val))
- val = XCDR (val);
- }
- else if (!NILP (Vcoding_system_for_write))
- val = Vcoding_system_for_write;
- else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
- val = Qnil;
- else
- {
- if (EQ (coding_systems, Qt))
- {
- if (NILP (host) || NILP (service))
- coding_systems = Qnil;
- else
- coding_systems = CALLN (Ffind_operation_coding_system,
- Qopen_network_stream, name, p->buffer,
- host, service);
- }
- if (CONSP (coding_systems))
- val = XCDR (coding_systems);
- else if (CONSP (Vdefault_process_coding_system))
- val = XCDR (Vdefault_process_coding_system);
- else
- val = Qnil;
- }
- pset_encode_coding_system (p, val);
- }
- setup_process_coding_systems (proc);
+ if (!NILP (tem))
+ {
+ val = XCAR (XCDR (tem));
+ if (CONSP (val))
+ val = XCDR (val);
+ }
+ else if (!NILP (Vcoding_system_for_write))
+ val = Vcoding_system_for_write;
+ else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
+ val = Qnil;
+ else
+ {
+ if (EQ (coding_systems, Qt))
+ {
+ if (NILP (host) || NILP (service))
+ coding_systems = Qnil;
+ else
+ coding_systems = CALLN (Ffind_operation_coding_system,
+ Qopen_network_stream, name, p->buffer,
+ host, service);
+ }
+ if (CONSP (coding_systems))
+ val = XCDR (coding_systems);
+ else if (CONSP (Vdefault_process_coding_system))
+ val = XCDR (Vdefault_process_coding_system);
+ else
+ val = Qnil;
+ }
+ pset_encode_coding_system (p, val);
pset_decoding_buf (p, empty_unibyte_string);
p->decoding_carryover = 0;
= !(!NILP (tem) || NILP (p->buffer) || !inherit_process_coding_system);
}
-void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses) {
+void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
+{
ptrdiff_t count = SPECPDL_INDEX ();
ptrdiff_t count1;
int s = -1, outch, inch;
int xerrno = 0;
Lisp_Object ip_address;
int family;
- struct sockaddr *sa;
+ struct sockaddr *sa = NULL;
int ret;
int addrlen;
struct Lisp_Process *p = XPROCESS (proc);
Lisp_Object contact = p->childp;
int optbits = 0;
- /* Do this in case we never enter the for-loop below. */
+ /* Do this in case we never enter the while-loop below. */
count1 = SPECPDL_INDEX ();
s = -1;
while (!NILP (ip_addresses))
{
- ip_address = Fcar (ip_addresses);
- ip_addresses = Fcdr (ip_addresses);
+ ip_address = XCAR (ip_addresses);
+ ip_addresses = XCDR (ip_addresses);
#ifdef WINDOWSNT
retry_connect:
#endif
addrlen = get_lisp_to_sockaddr_size (ip_address, &family);
- sa = alloca (addrlen);
+ if (sa)
+ free (sa);
+ sa = xmalloc (addrlen);
conv_lisp_to_sockaddr (family, ip_address, sa, addrlen);
s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol);
{
Lisp_Object params = contact, key, val;
- while (!NILP (params)) {
- key = Fcar (params);
- params = Fcdr (params);
- val = Fcar (params);
- params = Fcdr (params);
- optbits |= set_socket_option (s, key, val);
- }
+ while (!NILP (params))
+ {
+ key = XCAR (params);
+ params = XCDR (params);
+ val = XCAR (params);
+ params = XCDR (params);
+ optbits |= set_socket_option (s, key, val);
+ }
}
if (p->is_server)
Lisp_Object service;
service = make_number (ntohs (sa1.sin_port));
contact = Fplist_put (contact, QCservice, service);
+ // Save the port number so that we can stash it in
+ // the process object later.
+ ((struct sockaddr_in *)sa)->sin_port = sa1.sin_port;
}
}
#endif
}
#endif
- contact = Fplist_put (contact, p->is_server? QCremote: QClocal,
+ contact = Fplist_put (contact, p->is_server? QClocal: QCremote,
conv_sockaddr_to_lisp (sa, addrlen));
#ifdef HAVE_GETSOCKNAME
if (!p->is_server)
if (inch > max_process_desc)
max_process_desc = inch;
- set_network_socket_coding_system (proc);
+ setup_process_coding_systems (proc);
+
+#ifdef HAVE_GNUTLS
+ /* Continue the asynchronous connection. */
+ if (!NILP (p->gnutls_boot_parameters))
+ {
+ Lisp_Object boot, params = p->gnutls_boot_parameters;
+
+ boot = Fgnutls_boot (proc, XCAR (params), XCDR (params));
+ p->gnutls_boot_parameters = Qnil;
+
+ if (NILP (boot) || STRINGP (boot) ||
+ p->gnutls_initstage != GNUTLS_STAGE_READY)
+ {
+ deactivate_process (proc);
+ if (NILP (boot))
+ pset_status (p, list2 (Qfailed,
+ build_string ("TLS negotiation failed")));
+ else
+ pset_status (p, list2 (Qfailed, boot));
+ }
+ else
+ {
+ Lisp_Object result = Qt;
+
+ if (!NILP (Ffboundp (Qnsm_verify_connection)))
+ result = call3 (Qnsm_verify_connection,
+ proc,
+ Fplist_get (contact, QChost),
+ Fplist_get (contact, QCservice));
+
+ if (NILP (result))
+ {
+ pset_status (p, list2 (Qfailed,
+ build_string ("The Network Security Manager stopped the connections")));
+ deactivate_process (proc);
+ }
+ else
+ {
+ /* If we cleared the connection wait mask before we did
+ the TLS setup, then we have to say that the process
+ is finally "open" here. */
+ if (! FD_ISSET (p->outfd, &connect_wait_mask))
+ {
+ pset_status (p, Qrun);
+ /* Execute the sentinel here. If we had relied on
+ status_notify to do it later, it will read input
+ from the process before calling the sentinel. */
+ exec_sentinel (proc, build_string ("open\n"));
+ }
+ }
+ }
+ }
+#endif
+
}
+#ifndef HAVE_GETADDRINFO
+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;
+}
+#endif
/* Create a network stream/datagram client/server process. Treated
exactly like a normal process when reading and writing. Primary
is a cons (DECODING . ENCODING), DECODING is used for reading, and
ENCODING is used for writing.
-:nowait BOOL -- If BOOL is non-nil for a stream type client process,
-return without waiting for the connection to complete; instead, the
-sentinel function will be called with second arg matching "open" (if
-successful) or "failed" when the connect completes. Default is to use
-a blocking connect (i.e. wait) for stream type connections.
+:nowait BOOL -- If NOWAIT is non-nil for a stream type client
+process, return without waiting for the connection to complete;
+instead, the sentinel function will be called with second arg matching
+"open" (if successful) or "failed" when the connect completes.
+Default is to use a blocking connect (i.e. wait) for stream type
+connections.
:noquery BOOL -- Query the user unless BOOL is non-nil, and process is
running when Emacs is exited.
:plist PLIST -- Install PLIST as the new process's initial plist.
+:tls-parameters LIST -- is a list that should be supplied if you're
+opening a TLS connection. The first element is the TLS type (either
+`gnutls-x509pki' or `gnutls-anon'), and the remaining elements should
+be a keyword list accepted by gnutls-boot (as returned by
+`gnutls-boot-parameters').
+
:server QLEN -- if QLEN is non-nil, create a server process for the
specified FAMILY, SERVICE, and connection type (stream or datagram).
If QLEN is an integer, it is used as the max. length of the server's
Lisp_Object proc;
Lisp_Object contact;
struct Lisp_Process *p;
-#ifdef HAVE_GETADDRINFO
- struct addrinfo ai, *res, *lres;
- struct addrinfo hints;
+#if defined(HAVE_GETADDRINFO) || defined(HAVE_GETADDRINFO_A)
+ struct addrinfo *hints;
const char *portstring;
char portbuf[128];
-#endif /* HAVE_GETADDRINFO */
+#endif
#ifdef HAVE_LOCAL_SOCKETS
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;
int socktype;
int family = -1;
int ai_protocol = 0;
+#ifdef HAVE_GETADDRINFO_A
+ struct gaicb **dns_requests = NULL;
+#endif
ptrdiff_t count = SPECPDL_INDEX ();
if (nargs == 0)
CHECK_STRING (name);
- /* Initialize addrinfo structure in case we don't use getaddrinfo. */
- ai.ai_socktype = socktype;
- ai.ai_protocol = 0;
- ai.ai_next = NULL;
- res = &ai;
-
/* :local ADDRESS or :remote ADDRESS */
tem = Fplist_get (contact, QCserver);
if (!NILP (tem))
/* :host HOST -- hostname, ip address, or 'local for localhost. */
host = Fplist_get (contact, QChost);
- if (!NILP (host))
+ if (NILP (host))
+ {
+ /* The "connection" function gets it bind info from the address we're
+ given, so use this dummy address if nothing is specified. */
+#ifdef HAVE_LOCAL_SOCKETS
+ if (family != AF_LOCAL)
+#endif
+ host = build_string ("127.0.0.1");
+ }
+ else
{
if (EQ (host, Qlocal))
/* Depending on setup, "localhost" may map to different IPv4 and/or
}
#endif
-#ifdef HAVE_GETADDRINFO
- /* If we have a host, use getaddrinfo to resolve both host and service.
- Otherwise, use getservbyname to lookup the service. */
-
+#if defined (HAVE_GETADDRINFO) || defined (HAVE_GETADDRINFO_A)
if (!NILP (host))
{
portstring = SSDATA (service);
}
+ hints = xzalloc (sizeof (struct addrinfo));
+ hints->ai_flags = 0;
+ hints->ai_family = family;
+ hints->ai_socktype = socktype;
+ hints->ai_protocol = 0;
+ }
+
+#endif
+
+#ifdef HAVE_GETADDRINFO_A
+ 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));
+ dns_requests[0]->ar_name = strdup (SSDATA (host));
+ dns_requests[0]->ar_service = strdup (portstring);
+ dns_requests[0]->ar_request = hints;
+ dns_requests[0]->ar_result = NULL;
+
+ ret = getaddrinfo_a (GAI_NOWAIT, dns_requests, 1, NULL);
+ if (ret)
+ error ("%s/%s getaddrinfo_a error %d", SSDATA (host), portstring, ret);
+
+ goto open_socket;
+ }
+#endif /* HAVE_GETADDRINFO_A */
+
+#ifdef HAVE_GETADDRINFO
+ /* If we have a host, use getaddrinfo to resolve both host and service.
+ Otherwise, use getservbyname to lookup the service. */
+
+ if (!NILP (host))
+ {
+ struct addrinfo *res, *lres;
+ int ret;
+
immediate_quit = 1;
QUIT;
- memset (&hints, 0, sizeof (hints));
- hints.ai_flags = 0;
- hints.ai_family = family;
- hints.ai_socktype = socktype;
- hints.ai_protocol = 0;
#ifdef HAVE_RES_INIT
res_init ();
#endif
- ret = getaddrinfo (SSDATA (host), portstring, &hints, &res);
+ ret = getaddrinfo (SSDATA (host), portstring, hints, &res);
if (ret)
#ifdef HAVE_GAI_STRERROR
error ("%s/%s %s", SSDATA (host), portstring, gai_strerror (ret));
(lres->ai_addr, lres->ai_addrlen),
ip_addresses);
ai_protocol = lres->ai_protocol;
- family = lres->ai_family;
}
+ ip_addresses = Fnreverse (ip_addresses);
+
+ freeaddrinfo (res);
+ xfree (hints);
+
goto open_socket;
}
#endif /* HAVE_GETADDRINFO */
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;
(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
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);
- family = host_info_ptr->h_addrtype;
}
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);
}
}
p->port = port;
p->socktype = socktype;
p->ai_protocol = ai_protocol;
+#ifdef HAVE_GETADDRINFO_A
+ p->dns_requests = NULL;
+#endif
+#ifdef HAVE_GNUTLS
+ tem = Fplist_get (contact, QCtls_parameters);
+ CHECK_LIST (tem);
+ p->gnutls_boot_parameters = tem;
+#endif
+
+ set_network_socket_coding_system (proc);
unbind_to (count, Qnil);
#endif
}
+#ifdef HAVE_GETADDRINFO_A
+ /* If we're doing async address resolution, the list of addresses
+ here will be nil, so we postpone connecting to the server. */
+ if (!p->is_server && NILP (ip_addresses))
+ {
+ p->dns_requests = dns_requests;
+ p->status = Qconnect;
+ dns_processes = Fcons (proc, dns_processes);
+ }
+ else
+ {
+ connect_network_socket (proc, ip_addresses);
+ }
+#else /* HAVE_GETADDRINFO_A */
connect_network_socket (proc, ip_addresses);
+#endif
+
return proc;
}
exec_sentinel (proc, concat3 (open_from, host_string, nl));
}
+#ifdef HAVE_GETADDRINFO_A
+static Lisp_Object
+check_for_dns (Lisp_Object proc)
+{
+ struct Lisp_Process *p = XPROCESS (proc);
+ Lisp_Object ip_addresses = Qnil;
+ int ret = 0;
+
+ /* Sanity check. */
+ if (! p->dns_requests)
+ return Qnil;
+
+ /* This process should not already be connected (or killed). */
+ if (!EQ (p->status, Qconnect))
+ return Qnil;
+
+ ret = gai_error (p->dns_requests[0]);
+ if (ret == EAI_INPROGRESS)
+ return Qt;
+
+ /* We got a response. */
+ if (ret == 0)
+ {
+ struct addrinfo *res;
+
+ for (res = p->dns_requests[0]->ar_result; res; res = res->ai_next)
+ {
+ ip_addresses = Fcons (conv_sockaddr_to_lisp
+ (res->ai_addr, res->ai_addrlen),
+ ip_addresses);
+ }
+
+ ip_addresses = Fnreverse (ip_addresses);
+ freeaddrinfo (p->dns_requests[0]->ar_result);
+ }
+ /* The DNS lookup failed. */
+ else
+ {
+ deactivate_process (proc);
+ pset_status (p, (list2
+ (Qfailed,
+ concat3 (build_string ("Name lookup of "),
+ build_string (p->dns_requests[0]->ar_name),
+ build_string (" failed")))));
+ }
+
+ xfree ((void *)p->dns_requests[0]->ar_request);
+ xfree ((void *)p->dns_requests[0]->ar_name);
+ xfree ((void *)p->dns_requests[0]->ar_service);
+ xfree (p->dns_requests[0]);
+ xfree (p->dns_requests);
+ p->dns_requests = NULL;
+
+ return ip_addresses;
+}
+
+#endif /* HAVE_GETADDRINFO_A */
+
+static void
+wait_for_socket_fds (Lisp_Object process, char *name)
+{
+ while (XPROCESS (process)->infd < 0 &&
+ EQ (XPROCESS (process)->status, Qconnect))
+ {
+ printf("Waiting for socket from %s...\n", name);
+ wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0);
+ }
+}
+
+static void
+wait_while_connecting (Lisp_Object process)
+{
+ while (EQ (XPROCESS (process)->status, Qconnect))
+ {
+ printf("Waiting for connection...\n");
+ wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0);
+ }
+}
+
+static void
+wait_for_tls_negotiation (Lisp_Object process)
+{
+#ifdef HAVE_GNUTLS
+ while (EQ (XPROCESS (process)->status, Qconnect) &&
+ !NILP (XPROCESS (process)->gnutls_boot_parameters))
+ {
+ printf("Waiting for TLS...\n");
+ wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0);
+ }
+#endif
+}
+
/* This variable is different from waiting_for_input in keyboard.c.
It is used to communicate to a lisp process-filter/sentinel (via the
function Fwaiting_for_user_input_p below) whether Emacs was waiting
if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
break;
+#ifdef HAVE_GETADDRINFO_A
+ if (!NILP (dns_processes))
+ {
+ Lisp_Object dns_list = dns_processes, dns, ip_addresses,
+ answers = Qnil, answer, new = Qnil;
+ struct Lisp_Process *p;
+
+ /* This is programmed in a somewhat awkward fashion because
+ calling connect_network_socket might make us end up back
+ here again, and we would have a race condition with
+ segfaults. So first go through all pending requests and see
+ whether we got any answers. */
+ while (!NILP (dns_list))
+ {
+ dns = XCAR (dns_list);
+ dns_list = XCDR (dns_list);
+ p = XPROCESS (dns);
+ if (p && p->dns_requests)
+ {
+ if (! wait_proc || p == wait_proc)
+ {
+ ip_addresses = check_for_dns (dns);
+ if (EQ (ip_addresses, Qt))
+ new = Fcons (dns, new);
+ else
+ answers = Fcons (Fcons (dns, ip_addresses), answers);
+ }
+ else
+ new = Fcons (dns, new);
+ }
+ }
+
+ /* Replace with the list of DNS requests still not responded
+ to. */
+ dns_processes = new;
+
+ /* Then continue the connection for the successful
+ requests. */
+ while (!NILP (answers))
+ {
+ answer = XCAR (answers);
+ answers = XCDR (answers);
+ if (!NILP (XCDR (answer)))
+ connect_network_socket (XCAR (answer), XCDR (answer));
+ }
+ }
+#endif /* HAVE_GETADDRINFO_A */
+
/* Compute time from now till when time limit is up. */
/* Exit if already run out. */
if (wait == TIMEOUT)
}
else
{
- pset_status (p, Qrun);
- /* Execute the sentinel here. If we had relied on
- status_notify to do it later, it will read input
- from the process before calling the sentinel. */
- exec_sentinel (proc, build_string ("open\n"));
+ if (NILP (p->gnutls_boot_parameters))
+ {
+ pset_status (p, Qrun);
+ /* Execute the sentinel here. If we had relied on
+ status_notify to do it later, it will read input
+ from the process before calling the sentinel. */
+ exec_sentinel (proc, build_string ("open\n"));
+ }
+
if (0 <= p->infd && !EQ (p->filter, Qt)
&& !EQ (p->command, Qt))
{
ssize_t rv;
struct coding_system *coding;
+ if (NETCONN_P (proc)) {
+ wait_while_connecting (proc);
+ wait_for_tls_negotiation (proc);
+ }
+
if (p->raw_status_new)
update_status (p);
if (! EQ (p->status, Qrun))
if (XINT (start) < GPT && XINT (end) > GPT)
move_gap_both (XINT (start), start_byte);
+ if (NETCONN_P (proc))
+ wait_while_connecting (proc);
+
send_process (proc, (char *) BYTE_POS_ADDR (start_byte),
end_byte - start_byte, Fcurrent_buffer ());
Lisp_Object proc;
CHECK_STRING (string);
proc = get_process (process);
+
send_process (proc, SSDATA (string),
SBYTES (string), string);
return Qnil;
struct coding_system *coding = NULL;
int outfd;
- if (DATAGRAM_CONN_P (process))
+ proc = get_process (process);
+
+ if (NETCONN_P (proc))
+ wait_while_connecting (proc);
+
+ if (DATAGRAM_CONN_P (proc))
return process;
- proc = get_process (process);
+
outfd = XPROCESS (proc)->outfd;
if (outfd >= 0)
coding = proc_encode_coding_system[outfd];
register struct Lisp_Process *p;
CHECK_PROCESS (process);
+
+ if (NETCONN_P (process))
+ wait_for_socket_fds (process, "set-process-coding-system");
+
p = XPROCESS (process);
+
if (p->infd < 0)
error ("Input file descriptor of %s closed", SDATA (p->name));
if (p->outfd < 0)
register struct Lisp_Process *p;
CHECK_PROCESS (process);
+
+ if (NETCONN_P (process))
+ wait_for_socket_fds (process, "set-process-filter-multibyte");
+
p = XPROCESS (process);
if (NILP (flag))
pset_decode_coding_system
#ifdef DATAGRAM_SOCKETS
memset (datagram_address, 0, sizeof datagram_address);
#endif
+#ifdef HAVE_GETADDRINFO_A
+ dns_processes = Qnil;
+#endif
#if defined (DARWIN_OS)
/* PTYs are broken on Darwin < 6, but are sometimes useful for interactive
DEFSYM (QCserver, ":server");
DEFSYM (QCnowait, ":nowait");
DEFSYM (QCsentinel, ":sentinel");
+ DEFSYM (QCtls_parameters, ":tls-parameters");
+ DEFSYM (Qnsm_verify_connection, "nsm-verify-connection");
DEFSYM (QClog, ":log");
DEFSYM (QCnoquery, ":noquery");
DEFSYM (QCstop, ":stop");
staticpro (&Vprocess_alist);
staticpro (&deleted_pid_list);
+#ifdef HAVE_GETADDRINFO_A
+ staticpro (&dns_processes);
+#endif
#endif /* subprocesses */