unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#17976: 24.3; url-retrieve-synchronously doesn't fallback to IPv4
@ 2014-07-09 12:38 Juliusz Chroboczek
  2014-07-09 13:06 ` Andreas Schwab
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Juliusz Chroboczek @ 2014-07-09 12:38 UTC (permalink / raw)
  To: 17976


My machine has both IPv6 and IPv4.  I'm accessing a server that has both
IPv6 and IPv4, but whose web server listens on IPv4 only.  The web server
is doing the right thing, sending RST upon IPv6 connection attempts.  Wget
and telnet do the right thing, they fallback to IPv4:

  $ telnet moule.informatique.univ-paris-diderot.fr 8080
  Trying 2001:660:3301:8070::40...
  Trying 194.254.199.40...
  Connected to moule.informatique.univ-paris-diderot.fr.
  Escape character is '^]'.

On the other hand, url-retrieve-synchronously returns an empty string.
Tcpdump shows that it's never even trying IPv4:

  (with-current-buffer
    (url-retrieve-synchronously
     "http://moule.informatique.univ-paris-diderot.fr:8080")
    (buffer-substring (point-min) (point-max)))
  ""

  (with-current-buffer
    (url-retrieve-synchronously "http://194.254.199.40:8080")
    (buffer-substring (point-min) (point-max)))
  "HTTP/1.1 200 OK
  ..."





^ permalink raw reply	[flat|nested] 17+ messages in thread
* bug#23620: 24.3; url-retrieve-synchronously doesn't fallback to IPv4
@ 2016-06-26 21:58 Paul Eggert
  2016-06-26 23:20 ` Juliusz Chroboczek
  0 siblings, 1 reply; 17+ messages in thread
From: Paul Eggert @ 2016-06-26 21:58 UTC (permalink / raw)
  To: 17976
  Cc: Juliusz Chroboczek, Andreas Schwab, 23620, Artur Malabarba,
	Lars Ingebrigtsen

[-- Attachment #1: Type: text/plain, Size: 579 bytes --]

No further comment on the proposed patch, and as it should be a win for 
non-WINDOWSNT I decided to install it on the Emacs master branch. I 
looked into how libcurl addresses the issue, and it doesn't care whether 
the errno value reported by getsockopt is ECONNREFUSED so I adjusted the 
Emacs patch accordingly (see attached) before installing. Please give it 
a try if you have the time.

This patch does not affect behavior if WINDOWSNT. If the bug does not 
occur on MS-Windows I hope we can close Bug#17976. Otherwise we should 
leave the bug open for the WINDOWSNT case.

[-- Attachment #2: 0001-Try-other-addresses-when-connecting-to-multihomed.patch --]
[-- Type: text/x-patch, Size: 6589 bytes --]

From 6a90b600323afc42ae3bd644d82ba7ea054a816a Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sun, 26 Jun 2016 23:27:21 +0200
Subject: [PATCH] Try other addresses when connecting to multihomed

Problem reported by Juliusz Chroboczek (Bug#17976)
and by Artur Malabarba (Bug#23620).
Patch from a suggestion by Andreas Schwab in:
http://bugs.gnu.org/17976#39
This patch is for non-MS-Windows platforms.
I don't know the situation on MS-Windows.
* src/process.c (connecting_status):
New function, for (connect . ADDRINFOS).
(connect_network_socket, check_for_dns, wait_for_socket_fds)
(wait_while_connecting, wait_reading_process_output, status_notify):
Use it.
(decode_status, Fmake_network_process):
Support (connect . ADDRINFOS) status.
(connect_network_socket) [!WINDOWSNT]:
If the connection failed and there are other addresses to try, do not
signal an error; instead, loop around to try the next address.
(wait_reading_process_output): Advance to the next address
if there are multiple addresses and the first remaining address
failed.
* src/process.h (struct Lisp_Process.status): Adjust comment
to describe (connect . ADDRINFOS).
---
 src/process.c | 47 +++++++++++++++++++++++++++++++++++------------
 src/process.h |  4 +++-
 2 files changed, 38 insertions(+), 13 deletions(-)

diff --git a/src/process.c b/src/process.c
index e669278..ed0c529 100644
--- a/src/process.c
+++ b/src/process.c
@@ -533,6 +533,14 @@ status_convert (int w)
     return Qrun;
 }
 
+/* True if STATUS is that of a process attempting connection.  */
+
+static bool
+connecting_status (Lisp_Object status)
+{
+  return CONSP (status) && EQ (XCAR (status), Qconnect);
+}
+
 /* Given a status-list, extract the three pieces of information
    and store them individually through the three pointers.  */
 
@@ -542,6 +550,9 @@ decode_status (Lisp_Object l, Lisp_Object *symbol, Lisp_Object *code,
 {
   Lisp_Object tem;
 
+  if (connecting_status (l))
+    l = XCAR (l);
+
   if (SYMBOLP (l))
     {
       *symbol = l;
@@ -3288,9 +3299,10 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
 	  eassert (FD_ISSET (s, &fdset));
 	  if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) < 0)
 	    report_file_error ("Failed getsockopt", Qnil);
-	  if (xerrno)
+	  if (xerrno == 0)
+	    break;
+	  if (NILP (addrinfos))
 	    report_file_errno ("Failed connect", Qnil, xerrno);
-	  break;
 	}
 #endif /* !WINDOWSNT */
 
@@ -3399,7 +3411,9 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
       /* We may get here if connect did succeed immediately.  However,
 	 in that case, we still need to signal this like a non-blocking
 	 connection.  */
-      pset_status (p, Qconnect);
+      if (! (connecting_status (p->status)
+	     && EQ (XCDR (p->status), addrinfos)))
+	pset_status (p, Fcons (Qconnect, addrinfos));
       if (!FD_ISSET (inch, &connect_wait_mask))
 	{
 	  FD_SET (inch, &connect_wait_mask);
@@ -3960,7 +3974,7 @@ usage: (make-network-process &rest ARGS)  */)
   if (!p->is_server && NILP (addrinfos))
     {
       p->dns_request = dns_request;
-      p->status = Qconnect;
+      p->status = list1 (Qconnect);
       return proc;
     }
 #endif
@@ -4673,7 +4687,7 @@ check_for_dns (Lisp_Object proc)
       addrinfos = Fnreverse (addrinfos);
     }
   /* The DNS lookup failed. */
-  else if (EQ (p->status, Qconnect))
+  else if (connecting_status (p->status))
     {
       deactivate_process (proc);
       pset_status (p, (list2
@@ -4686,7 +4700,7 @@ check_for_dns (Lisp_Object proc)
   free_dns_request (proc);
 
   /* This process should not already be connected (or killed). */
-  if (!EQ (p->status, Qconnect))
+  if (! connecting_status (p->status))
     return Qnil;
 
   return addrinfos;
@@ -4698,7 +4712,7 @@ static void
 wait_for_socket_fds (Lisp_Object process, char const *name)
 {
   while (XPROCESS (process)->infd < 0
-	 && EQ (XPROCESS (process)->status, Qconnect))
+	 && connecting_status (XPROCESS (process)->status))
     {
       add_to_log ("Waiting for socket from %s...", build_string (name));
       wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0);
@@ -4708,7 +4722,7 @@ wait_for_socket_fds (Lisp_Object process, char const *name)
 static void
 wait_while_connecting (Lisp_Object process)
 {
-  while (EQ (XPROCESS (process)->status, Qconnect))
+  while (connecting_status (XPROCESS (process)->status))
     {
       add_to_log ("Waiting for connection...");
       wait_reading_process_output (0, 20 * 1000 * 1000, 0, 0, Qnil, NULL, 0);
@@ -5010,7 +5024,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 	update_status (wait_proc);
       if (wait_proc
 	  && ! EQ (wait_proc->status, Qrun)
-	  && ! EQ (wait_proc->status, Qconnect))
+	  && ! connecting_status (wait_proc->status))
 	{
 	  bool read_some_bytes = false;
 
@@ -5520,9 +5534,18 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 #endif
 	      if (xerrno)
 		{
-		  p->tick = ++process_tick;
-		  pset_status (p, list2 (Qfailed, make_number (xerrno)));
+		  Lisp_Object addrinfos
+		    = connecting_status (p->status) ? XCDR (p->status) : Qnil;
+		  if (!NILP (addrinfos))
+		    XSETCDR (p->status, XCDR (addrinfos));
+		  else
+		    {
+		      p->tick = ++process_tick;
+		      pset_status (p, list2 (Qfailed, make_number (xerrno)));
+		    }
 		  deactivate_process (proc);
+		  if (!NILP (addrinfos))
+		    connect_network_socket (proc, addrinfos, Qnil);
 		}
 	      else
 		{
@@ -6999,7 +7022,7 @@ status_notify (struct Lisp_Process *deleting_process,
 
 	  /* If process is still active, read any output that remains.  */
 	  while (! EQ (p->filter, Qt)
-		 && ! EQ (p->status, Qconnect)
+		 && ! connecting_status (p->status)
 		 && ! EQ (p->status, Qlisten)
 		 /* Network or serial process not stopped:  */
 		 && ! EQ (p->command, Qt)
diff --git a/src/process.h b/src/process.h
index 4430377..6c227bc 100644
--- a/src/process.h
+++ b/src/process.h
@@ -83,7 +83,9 @@ struct Lisp_Process
     Lisp_Object mark;
 
     /* Symbol indicating status of process.
-       This may be a symbol: run, open, closed, listen, connect, or failed.
+       This may be a symbol: run, open, closed, listen, or failed.
+       Or it may be a pair (connect . ADDRINFOS) where ADDRINFOS is
+       a list of remaining (PROTOCOL . ADDRINFO) pairs to try.
        Or it may be (failed ERR) where ERR is an integer, string or symbol.
        Or it may be a list, whose car is stop, exit or signal
        and whose cdr is a pair (EXIT_CODE . COREDUMP_FLAG)
-- 
2.5.5


^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2017-10-21 23:55 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-09 12:38 bug#17976: 24.3; url-retrieve-synchronously doesn't fallback to IPv4 Juliusz Chroboczek
2014-07-09 13:06 ` Andreas Schwab
2014-07-09 20:25   ` Juliusz Chroboczek
2014-07-10  7:17     ` Andreas Schwab
2014-07-10 20:28       ` Juliusz Chroboczek
2014-07-10 20:54       ` Juliusz Chroboczek
2014-07-11 12:21     ` Andreas Schwab
2015-12-25 20:33 ` Lars Ingebrigtsen
2015-12-25 20:43   ` Eli Zaretskii
2015-12-25 20:48     ` Lars Ingebrigtsen
2015-12-25 21:14       ` Andreas Schwab
2015-12-25 21:23         ` Lars Ingebrigtsen
2015-12-25 21:44           ` Andreas Schwab
2015-12-25 23:15           ` Juliusz Chroboczek
2015-12-25 21:00   ` Andreas Schwab
2016-06-12 18:36 ` Paul Eggert
  -- strict thread matches above, loose matches on Subject: below --
2016-06-26 21:58 bug#23620: " Paul Eggert
2016-06-26 23:20 ` Juliusz Chroboczek
2017-10-21 23:55   ` bug#17976: " Noam Postavsky

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).