aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/process.c138
-rw-r--r--src/process.h12
2 files changed, 136 insertions, 14 deletions
diff --git a/src/process.c b/src/process.c
index b5d306f7de9..4f0c4e9bcdc 100644
--- a/src/process.c
+++ b/src/process.c
@@ -281,6 +281,10 @@ static int max_input_desc;
281 281
282/* Indexed by descriptor, gives the process (if any) for that descriptor. */ 282/* Indexed by descriptor, gives the process (if any) for that descriptor. */
283static Lisp_Object chan_process[FD_SETSIZE]; 283static Lisp_Object chan_process[FD_SETSIZE];
284#ifdef HAVE_GETADDRINFO_A
285/* Pending DNS requests. */
286static Lisp_Object dns_process[FD_SETSIZE];
287#endif
284 288
285/* Alist of elements (NAME . PROCESS). */ 289/* Alist of elements (NAME . PROCESS). */
286static Lisp_Object Vprocess_alist; 290static Lisp_Object Vprocess_alist;
@@ -3012,7 +3016,7 @@ void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
3012 Lisp_Object contact = p->childp; 3016 Lisp_Object contact = p->childp;
3013 int optbits = 0; 3017 int optbits = 0;
3014 3018
3015 /* Do this in case we never enter the for-loop below. */ 3019 /* Do this in case we never enter the while-loop below. */
3016 count1 = SPECPDL_INDEX (); 3020 count1 = SPECPDL_INDEX ();
3017 s = -1; 3021 s = -1;
3018 3022
@@ -3028,7 +3032,7 @@ void connect_network_socket (Lisp_Object proc, Lisp_Object ip_addresses)
3028 addrlen = get_lisp_to_sockaddr_size (ip_address, &family); 3032 addrlen = get_lisp_to_sockaddr_size (ip_address, &family);
3029 if (sa) 3033 if (sa)
3030 free (sa); 3034 free (sa);
3031 sa = alloca (addrlen); 3035 sa = xmalloc (addrlen);
3032 conv_lisp_to_sockaddr (family, ip_address, sa, addrlen); 3036 conv_lisp_to_sockaddr (family, ip_address, sa, addrlen);
3033 3037
3034 s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol); 3038 s = socket (family, p->socktype | SOCK_CLOEXEC, p->ai_protocol);
@@ -3469,7 +3473,7 @@ usage: (make-network-process &rest ARGS) */)
3469 struct Lisp_Process *p; 3473 struct Lisp_Process *p;
3470#ifdef HAVE_GETADDRINFO 3474#ifdef HAVE_GETADDRINFO
3471 struct addrinfo ai, *res, *lres; 3475 struct addrinfo ai, *res, *lres;
3472 struct addrinfo hints; 3476 struct addrinfo *hints;
3473 const char *portstring; 3477 const char *portstring;
3474 char portbuf[128]; 3478 char portbuf[128];
3475#endif /* HAVE_GETADDRINFO */ 3479#endif /* HAVE_GETADDRINFO */
@@ -3485,6 +3489,9 @@ usage: (make-network-process &rest ARGS) */)
3485 int socktype; 3489 int socktype;
3486 int family = -1; 3490 int family = -1;
3487 int ai_protocol = 0; 3491 int ai_protocol = 0;
3492#ifdef HAVE_GETADDRINFO_A
3493 struct gaicb *dns_request = NULL;
3494#endif
3488 ptrdiff_t count = SPECPDL_INDEX (); 3495 ptrdiff_t count = SPECPDL_INDEX ();
3489 3496
3490 if (nargs == 0) 3497 if (nargs == 0)
@@ -3610,10 +3617,7 @@ usage: (make-network-process &rest ARGS) */)
3610 } 3617 }
3611#endif 3618#endif
3612 3619
3613#ifdef HAVE_GETADDRINFO 3620#if defined (HAVE_GETADDRINFO) || defined (HAVE_GETADDRINFO_A)
3614 /* If we have a host, use getaddrinfo to resolve both host and service.
3615 Otherwise, use getservbyname to lookup the service. */
3616
3617 if (!NILP (host)) 3621 if (!NILP (host))
3618 { 3622 {
3619 3623
@@ -3632,19 +3636,51 @@ usage: (make-network-process &rest ARGS) */)
3632 portstring = SSDATA (service); 3636 portstring = SSDATA (service);
3633 } 3637 }
3634 3638
3639 hints = xmalloc (sizeof (struct addrinfo));
3640 memset (hints, 0, sizeof (struct addrinfo));
3641 hints->ai_flags = 0;
3642 hints->ai_family = family;
3643 hints->ai_socktype = socktype;
3644 hints->ai_protocol = 0;
3645 }
3646
3647#endif
3648
3649#ifdef HAVE_GETADDRINFO_A
3650 if (!NILP (Fplist_get (contact, QCnowait)) &&
3651 !NILP (host))
3652 {
3653 struct gaicb **reqs = xmalloc (sizeof (struct gaicb*));
3654
3655 dns_request = xmalloc (sizeof (struct gaicb));
3656 reqs[0] = dns_request;
3657 dns_request->ar_name = strdup (SSDATA (host));
3658 dns_request->ar_service = strdup (portstring);
3659 dns_request->ar_request = hints;
3660 dns_request->ar_result = NULL;
3661
3662 ret = getaddrinfo_a (GAI_NOWAIT, reqs, 1, NULL);
3663 if (ret)
3664 error ("%s/%s getaddrinfo_a error %d", SSDATA (host), portstring, ret);
3665
3666 goto open_socket;
3667 }
3668#endif /* HAVE_GETADDRINFO_A */
3669
3670#ifdef HAVE_GETADDRINFO
3671 /* If we have a host, use getaddrinfo to resolve both host and service.
3672 Otherwise, use getservbyname to lookup the service. */
3673
3674 if (!NILP (host))
3675 {
3635 immediate_quit = 1; 3676 immediate_quit = 1;
3636 QUIT; 3677 QUIT;
3637 memset (&hints, 0, sizeof (hints));
3638 hints.ai_flags = 0;
3639 hints.ai_family = family;
3640 hints.ai_socktype = socktype;
3641 hints.ai_protocol = 0;
3642 3678
3643#ifdef HAVE_RES_INIT 3679#ifdef HAVE_RES_INIT
3644 res_init (); 3680 res_init ();
3645#endif 3681#endif
3646 3682
3647 ret = getaddrinfo (SSDATA (host), portstring, &hints, &res); 3683 ret = getaddrinfo (SSDATA (host), portstring, hints, &res);
3648 if (ret) 3684 if (ret)
3649#ifdef HAVE_GAI_STRERROR 3685#ifdef HAVE_GAI_STRERROR
3650 error ("%s/%s %s", SSDATA (host), portstring, gai_strerror (ret)); 3686 error ("%s/%s %s", SSDATA (host), portstring, gai_strerror (ret));
@@ -3663,6 +3699,7 @@ usage: (make-network-process &rest ARGS) */)
3663 } 3699 }
3664 3700
3665 ip_addresses = Fnreverse (ip_addresses); 3701 ip_addresses = Fnreverse (ip_addresses);
3702 xfree (hints);
3666 3703
3667 goto open_socket; 3704 goto open_socket;
3668 } 3705 }
@@ -3749,6 +3786,7 @@ usage: (make-network-process &rest ARGS) */)
3749 p->port = port; 3786 p->port = port;
3750 p->socktype = socktype; 3787 p->socktype = socktype;
3751 p->ai_protocol = ai_protocol; 3788 p->ai_protocol = ai_protocol;
3789 p->dns_request = NULL;
3752 3790
3753 unbind_to (count, Qnil); 3791 unbind_to (count, Qnil);
3754 3792
@@ -3774,7 +3812,26 @@ usage: (make-network-process &rest ARGS) */)
3774#endif 3812#endif
3775 } 3813 }
3776 3814
3777 connect_network_socket (proc, ip_addresses); 3815 /* If we're doing async address resolution, the list of addresses
3816 here will be nil, so we postpone connecting to the server. */
3817 if (NILP (ip_addresses))
3818 {
3819 int channel;
3820
3821 p->dns_request = dns_request;
3822 p->status = Qconnect;
3823 for (channel = 0; channel < FD_SETSIZE; ++channel)
3824 if (NILP (dns_process[channel]))
3825 {
3826 dns_process[channel] = proc;
3827 break;
3828 }
3829 }
3830 else
3831 {
3832 connect_network_socket (proc, ip_addresses);
3833 }
3834
3778 return proc; 3835 return proc;
3779} 3836}
3780 3837
@@ -4479,6 +4536,40 @@ server_accept_connection (Lisp_Object server, int channel)
4479 exec_sentinel (proc, concat3 (open_from, host_string, nl)); 4536 exec_sentinel (proc, concat3 (open_from, host_string, nl));
4480} 4537}
4481 4538
4539#ifdef HAVE_GETADDRINFO_A
4540static int
4541check_for_dns (Lisp_Object proc)
4542{
4543 struct Lisp_Process *p = XPROCESS (proc);
4544 Lisp_Object ip_addresses = Qnil;
4545 int ret = 0;
4546
4547 ret = gai_error (p->dns_request);
4548 if (ret == EAI_INPROGRESS)
4549 return 0;
4550
4551 /* We got a response. */
4552 if (ret == 0)
4553 {
4554 struct addrinfo *res;
4555
4556 for (res = p->dns_request->ar_result; res; res = res->ai_next)
4557 {
4558 ip_addresses = Fcons (conv_sockaddr_to_lisp
4559 (res->ai_addr, res->ai_addrlen),
4560 ip_addresses);
4561 }
4562
4563 ip_addresses = Fnreverse (ip_addresses);
4564 connect_network_socket (proc, ip_addresses);
4565 return 1;
4566 }
4567
4568 pset_status (p, Qfailed);
4569 return 0;
4570}
4571#endif /* HAVE_GETADDRINFO_A */
4572
4482/* This variable is different from waiting_for_input in keyboard.c. 4573/* This variable is different from waiting_for_input in keyboard.c.
4483 It is used to communicate to a lisp process-filter/sentinel (via the 4574 It is used to communicate to a lisp process-filter/sentinel (via the
4484 function Fwaiting_for_user_input_p below) whether Emacs was waiting 4575 function Fwaiting_for_user_input_p below) whether Emacs was waiting
@@ -4604,6 +4695,22 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
4604 if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) 4695 if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
4605 break; 4696 break;
4606 4697
4698#ifdef HAVE_GETADDRINFO_A
4699 for (channel = 0; channel < FD_SETSIZE; ++channel)
4700 {
4701 if (! NILP (dns_process[channel]))
4702 {
4703 struct Lisp_Process *p = XPROCESS (dns_process[channel]);
4704 if (p && p->dns_request &&
4705 (! wait_proc || p == wait_proc) &&
4706 check_for_dns (dns_process[channel]))
4707 {
4708 dns_process[channel] = Qnil;
4709 }
4710 }
4711 }
4712#endif /* HAVE_GETADDRINFO_A */
4713
4607 /* Compute time from now till when time limit is up. */ 4714 /* Compute time from now till when time limit is up. */
4608 /* Exit if already run out. */ 4715 /* Exit if already run out. */
4609 if (wait == TIMEOUT) 4716 if (wait == TIMEOUT)
@@ -7450,6 +7557,9 @@ init_process_emacs (void)
7450 { 7557 {
7451 chan_process[i] = Qnil; 7558 chan_process[i] = Qnil;
7452 proc_buffered_char[i] = -1; 7559 proc_buffered_char[i] = -1;
7560#ifdef HAVE_GETADDRINFO_A
7561 dns_process[i] = Qnil;
7562#endif
7453 } 7563 }
7454 memset (proc_decode_coding_system, 0, sizeof proc_decode_coding_system); 7564 memset (proc_decode_coding_system, 0, sizeof proc_decode_coding_system);
7455 memset (proc_encode_coding_system, 0, sizeof proc_encode_coding_system); 7565 memset (proc_encode_coding_system, 0, sizeof proc_encode_coding_system);
diff --git a/src/process.h b/src/process.h
index e2e6ca92984..684434c1748 100644
--- a/src/process.h
+++ b/src/process.h
@@ -161,14 +161,26 @@ struct Lisp_Process
161 flag indicates that `raw_status' contains a new status that still 161 flag indicates that `raw_status' contains a new status that still
162 needs to be synced to `status'. */ 162 needs to be synced to `status'. */
163 bool_bf raw_status_new : 1; 163 bool_bf raw_status_new : 1;
164 /* Whether this is a nonblocking socket. */
164 bool_bf is_non_blocking_client : 1; 165 bool_bf is_non_blocking_client : 1;
166 /* Whether this is a server or a client socket. */
165 bool_bf is_server : 1; 167 bool_bf is_server : 1;
166 int raw_status; 168 int raw_status;
169 /* The length of the socket backlog. */
167 int backlog; 170 int backlog;
171 /* The port number. */
168 int port; 172 int port;
173 /* The socket type. */
169 int socktype; 174 int socktype;
175 /* The socket protocol. */
170 int ai_protocol; 176 int ai_protocol;
171 177
178#ifdef HAVE_GETADDRINFO_A
179 /* Whether the socket is waiting for response from an asynchronous
180 DNS call. */
181 struct gaicb* dns_request;
182#endif
183
172#ifdef HAVE_GNUTLS 184#ifdef HAVE_GNUTLS
173 gnutls_initstage_t gnutls_initstage; 185 gnutls_initstage_t gnutls_initstage;
174 gnutls_session_t gnutls_state; 186 gnutls_session_t gnutls_state;