Skip to content

Instantly share code, notes, and snippets.

@gtk2k
Created March 11, 2017 11:43
Show Gist options
  • Save gtk2k/02f6315f3634686e5e072fd03fc2c26c to your computer and use it in GitHub Desktop.
Save gtk2k/02f6315f3634686e5e072fd03fc2c26c to your computer and use it in GitHub Desktop.
android proxy server
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