Created
March 11, 2017 11:43
-
-
Save gtk2k/02f6315f3634686e5e072fd03fc2c26c to your computer and use it in GitHub Desktop.
android proxy server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Android.App; | |
using Android.OS; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Net; | |
using System.Threading; | |
using System.Threading.Tasks; | |
namespace App1 | |
{ | |
[Activity(Label = "App1", MainLauncher = true, Icon = "@drawable/icon")] | |
public class MainActivity : Activity | |
{ | |
class ConcurrentList<TValue> | |
{ | |
private object _lock = new object(); | |
private List<TValue> _storage = new List<TValue>(); | |
public TValue this[int index] | |
{ | |
get | |
{ | |
lock (_lock) | |
{ | |
return _storage[index]; | |
} | |
} | |
set | |
{ | |
lock (_lock) | |
{ | |
_storage[index] = value; | |
} | |
} | |
} | |
public int Count | |
{ | |
get | |
{ | |
lock (_lock) | |
{ | |
return _storage.Count; | |
} | |
} | |
} | |
public void Add(TValue item) | |
{ | |
lock (_lock) | |
{ | |
_storage.Add(item); | |
} | |
} | |
public void Clear() | |
{ | |
lock (_lock) | |
{ | |
_storage.Clear(); | |
} | |
} | |
public bool Remove(TValue item) | |
{ | |
lock (_lock) | |
{ | |
return _storage.Remove(item); | |
} | |
} | |
} | |
private List<Stream> browserClients = new List<Stream>(); | |
private HttpListener listener; | |
private ConcurrentList<HttpListenerContext> contexts; | |
private bool isCamStreaming = false; | |
private Dictionary<string, string> headers = null; | |
private AutoResetEvent wait = new AutoResetEvent(false); | |
protected override void OnCreate(Bundle bundle) | |
{ | |
base.OnCreate(bundle); | |
// SP360へのリクエスト | |
var camReq = (HttpWebRequest)WebRequest.Create("http://10.0.2.2:8089"); | |
isCamStreaming = true; | |
camReq.BeginGetResponse(onCamResponse, camReq); | |
} | |
protected override void OnDestroy() | |
{ | |
base.OnDestroy(); | |
isCamStreaming = false; | |
} | |
private void startProxy() | |
{ | |
try | |
{ | |
// ブラウザーからのリクエストリスナー | |
listener = new HttpListener(); | |
contexts = new ConcurrentList<HttpListenerContext>(); | |
listener.Prefixes.Add("http://*:9001/"); | |
Task.Factory.StartNew(() => | |
{ | |
listener.Start(); | |
listener.BeginGetContext(onRequestReceived, null); | |
}); | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine(ex.Message); | |
} | |
} | |
private void onCamResponse(IAsyncResult ar) | |
{ | |
var camReq = (HttpWebRequest)ar.AsyncState; | |
var camRes = camReq.EndGetResponse(ar); | |
try | |
{ | |
if (headers == null) | |
{ | |
headers = new Dictionary<string, string>(); | |
foreach (var key in camRes.Headers.AllKeys) | |
{ | |
headers.Add(key, camRes.Headers[key]); | |
} | |
wait.Reset(); | |
startProxy(); | |
} | |
wait.WaitOne(); | |
while (isCamStreaming) | |
{ | |
for (var i = contexts.Count - 1; i >= 0; i--) | |
{ | |
try | |
{ | |
camRes.GetResponseStream().CopyTo(contexts[i].Response.OutputStream); | |
} | |
catch (IOException ex) | |
{ | |
Console.WriteLine(ex.Message); | |
contexts[i].Response.Close(); | |
contexts.Remove(contexts[i]); | |
if(contexts.Count == 0) | |
{ | |
wait.Reset(); | |
wait.WaitOne(); | |
} | |
} | |
} | |
} | |
} | |
catch (Exception ex) | |
{ | |
Console.WriteLine(ex.Message); | |
} | |
} | |
private void onRequestReceived(IAsyncResult result) | |
{ | |
try | |
{ | |
var context = listener.EndGetContext(result); | |
foreach (var kvp in headers) | |
{ | |
context.Response.Headers.Add(kvp.Key, kvp.Value); | |
} | |
contexts.Add(context); | |
wait.Set(); | |
listener.BeginGetContext(new AsyncCallback(onRequestReceived), null); | |
} | |
catch (Exception e) when (!listener.IsListening) | |
{ | |
Console.WriteLine("Listener ended.", e); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment