1 // Copyright (C) 2017 Kazuhiro Fujieda <fujieda@users.osdn.me>
\r
3 // Licensed under the Apache License, Version 2.0 (the "License");
\r
4 // you may not use this file except in compliance with the License.
\r
5 // You may obtain a copy of the License at
\r
7 // http://www.apache.org/licenses/LICENSE-2.0
\r
9 // Unless required by applicable law or agreed to in writing, software
\r
10 // distributed under the License is distributed on an "AS IS" BASIS,
\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
12 // See the License for the specific language governing permissions and
\r
13 // limitations under the License.
\r
18 using System.Net.Sockets;
\r
19 using System.Windows.Forms;
\r
20 using Microsoft.Win32;
\r
22 namespace KancolleSniffer
\r
24 public class ProxyManager
\r
26 private readonly Config _config;
\r
27 private readonly Control _parent;
\r
28 private readonly SystemProxy _systemProxy = new SystemProxy();
\r
29 private int _prevProxyPort;
\r
30 private int _autoConfigRetryCount;
\r
31 private readonly Timer _timer = new Timer {Interval = 1000};
\r
32 private bool _initiated;
\r
34 public ProxyManager(Config config, Control parent)
\r
38 SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
\r
39 _timer.Tick += CheckProxy;
\r
42 public bool ApplyConfig()
\r
44 if (!_config.Proxy.Auto)
\r
45 RestoreSystemProxy();
\r
46 if (_config.Proxy.UseUpstream)
\r
48 HttpProxy.UpstreamProxyHost = "127.0.0.1";
\r
49 HttpProxy.UpstreamProxyPort = _config.Proxy.UpstreamPort;
\r
51 HttpProxy.IsEnableUpstreamProxy = _config.Proxy.UseUpstream;
\r
53 if (!HttpProxy.IsInListening || _config.Proxy.Listen != _prevProxyPort)
\r
56 result = StartProxy();
\r
58 if (_config.Proxy.Auto && result)
\r
60 SetAndCheckAutoConfigUrl();
\r
62 _prevProxyPort = _config.Proxy.Listen;
\r
66 private bool StartProxy()
\r
70 HttpProxy.Startup(_config.Proxy.Listen, false, false);
\r
72 catch (SocketException e)
\r
74 if (e.SocketErrorCode != SocketError.AddressAlreadyInUse &&
\r
75 e.SocketErrorCode != SocketError.AccessDenied)
\r
79 if (WarnConflictPortNumber(_config.Proxy.Listen, _config.Proxy.Auto) == DialogResult.No ||
\r
80 !_config.Proxy.Auto)
\r
82 RestoreSystemProxy();
\r
85 HttpProxy.Startup(0, false, false);
\r
86 _config.Proxy.Listen = HttpProxy.LocalPort;
\r
91 private DialogResult WarnConflictPortNumber(int port, bool auto)
\r
93 var msg = $"ポート番号{port}は他のアプリケーションが使用中です。";
\r
94 var cap = "ポート番号の衝突";
\r
96 ? MessageBox.Show(_parent, msg + "自動的に別の番号を割り当てますか?", cap,
\r
97 MessageBoxButtons.YesNo, MessageBoxIcon.Question)
\r
98 : MessageBox.Show(_parent, msg + "設定ダイアログでポート番号を変更してください。", cap,
\r
99 MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
\r
102 private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
\r
104 if (e.Mode != PowerModes.Resume || !_config.Proxy.Auto)
\r
106 SystemProxy.Refresh();
\r
109 public void Shutdown()
\r
112 if (_config.Proxy.Auto)
\r
113 RestoreSystemProxy();
\r
114 SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged;
\r
117 private void ShutdownProxy()
\r
119 HttpProxy.Shutdown();
\r
122 private void SetAndCheckAutoConfigUrl()
\r
124 SetAutoConfigUrl();
\r
125 _initiated = false;
\r
129 private void CheckProxy(object sender, EventArgs ev)
\r
133 // Windows 10でプロキシ設定がいつの間にか消えるのに対応するために、
\r
134 // 設定が消えていないか毎秒確認して、消えていたら再設定する。
\r
135 if (IsProxyWorking)
\r
137 File.AppendAllText("proxy.log", $"[{DateTime.Now:G}] proxy setting vanished.\r\n");
\r
138 SetAutoConfigUrl();
\r
141 if (IsProxyWorking)
\r
146 if (_autoConfigRetryCount > 0 && _autoConfigRetryCount % 5 == 0)
\r
149 switch (MessageBox.Show(_parent, "プロキシの自動設定に失敗しました。", "エラー", MessageBoxButtons.AbortRetryIgnore,
\r
150 MessageBoxIcon.Error))
\r
152 case DialogResult.Abort:
\r
154 Environment.Exit(1);
\r
156 case DialogResult.Ignore:
\r
161 _autoConfigRetryCount++;
\r
162 SetAutoConfigUrl();
\r
165 private bool IsProxyWorking =>
\r
166 WebRequest.GetSystemWebProxy().GetProxy(new Uri("http://125.6.184.16/")).IsLoopback;
\r
168 private void SetAutoConfigUrl()
\r
170 var count = _autoConfigRetryCount == 0 ? "" : _autoConfigRetryCount.ToString();
\r
171 _systemProxy.SetAutoConfigUrl(
\r
172 $"http://localhost:{_config.Proxy.Listen}/proxy{count}.pac");
\r
175 private void RestoreSystemProxy()
\r
178 _systemProxy.RestoreSettings();
\r
181 public void UpdatePacFile()
\r
183 var request = (HttpWebRequest)WebRequest.Create("https://kancollesniffer.osdn.jp/proxy.pac");
\r
184 if (File.Exists("proxy.pac"))
\r
186 var date = File.GetLastWriteTime("proxy.pac");
\r
187 request.IfModifiedSince = date;
\r
191 var response = (HttpWebResponse)request.GetResponse();
\r
192 var mem = new MemoryStream();
\r
193 using (var stream = response.GetResponseStream())
\r
194 stream?.CopyTo(mem);
\r
196 using (var file = new FileStream("proxy.pac", FileMode.Create))
\r
199 // ReSharper disable once EmptyGeneralCatchClause
\r