diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/process.c | 138 | ||||
| -rw-r--r-- | src/process.h | 12 |
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. */ |
| 283 | static Lisp_Object chan_process[FD_SETSIZE]; | 283 | static Lisp_Object chan_process[FD_SETSIZE]; |
| 284 | #ifdef HAVE_GETADDRINFO_A | ||
| 285 | /* Pending DNS requests. */ | ||
| 286 | static Lisp_Object dns_process[FD_SETSIZE]; | ||
| 287 | #endif | ||
| 284 | 288 | ||
| 285 | /* Alist of elements (NAME . PROCESS). */ | 289 | /* Alist of elements (NAME . PROCESS). */ |
| 286 | static Lisp_Object Vprocess_alist; | 290 | static 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 | ||
| 4540 | static int | ||
| 4541 | check_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; |