OSDN Git Service

pbs.twimg.comへの接続にIPv4を強制するコードが意図した動作をしなかったことに対する修正
authorKimura Youichi <kim.upsilon@bucyou.net>
Tue, 11 Aug 2015 08:23:24 +0000 (17:23 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Tue, 11 Aug 2015 08:25:52 +0000 (17:25 +0900)
OpenTween/Connection/Networking.cs

index 86a1461..334a58e 100644 (file)
@@ -70,24 +70,10 @@ namespace OpenTween.Connection
                 if (forceIPv4 == value)
                     return;
 
-                if (value)
-                {
-                    BindIPEndPoint forceIPv4Delegate = (_, __, ___) => new IPEndPoint(IPAddress.Any, 0);
-
-                    ServicePointManager.FindServicePoint("http://pbs.twimg.com/", proxy)
-                        .BindIPEndPointDelegate = forceIPv4Delegate;
-                    ServicePointManager.FindServicePoint("https://pbs.twimg.com/", proxy)
-                        .BindIPEndPointDelegate = forceIPv4Delegate;
-                }
-                else
-                {
-                    ServicePointManager.FindServicePoint("http://pbs.twimg.com/", proxy)
-                        .BindIPEndPointDelegate = null;
-                    ServicePointManager.FindServicePoint("https://pbs.twimg.com/", proxy)
-                        .BindIPEndPointDelegate = null;
-                }
-
                 forceIPv4 = value;
+
+                // Network.Http を再作成させる
+                OnWebProxyChanged(EventArgs.Empty);
             }
         }
 
@@ -167,7 +153,12 @@ namespace OpenTween.Connection
                 handler.UseProxy = false;
             }
 
-            var client = new HttpClient(handler);
+            HttpClient client;
+            if (ForceIPv4)
+                client = new HttpClient(new ForceIPv4Handler(handler));
+            else
+                client = new HttpClient(handler);
+
             client.Timeout = Networking.DefaultTimeout;
             client.DefaultRequestHeaders.Add("User-Agent", Networking.GetUserAgentString());
 
@@ -201,6 +192,32 @@ namespace OpenTween.Connection
             if (WebProxyChanged != null)
                 WebProxyChanged(null, e);
         }
+
+        private class ForceIPv4Handler : DelegatingHandler
+        {
+            private readonly IPAddress ipv4Address;
+
+            public ForceIPv4Handler(HttpMessageHandler innerHandler)
+                : base(innerHandler)
+            {
+                foreach (var address in Dns.GetHostAddresses("pbs.twimg.com"))
+                    if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
+                        this.ipv4Address = address;
+            }
+
+            protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+            {
+                var requestUri = request.RequestUri;
+                if (requestUri.Host == "pbs.twimg.com")
+                {
+                    var rewriteUriStr = requestUri.GetLeftPart(UriPartial.Scheme) + this.ipv4Address + requestUri.PathAndQuery;
+                    request.RequestUri = new Uri(rewriteUriStr);
+                    request.Headers.Host = "pbs.twimg.com";
+                }
+
+                return base.SendAsync(request, cancellationToken);
+            }
+        }
     }
 
     public enum ProxyType