Commit e6a201e1 authored by Honfika's avatar Honfika

another race condition fix

parent 42ac058c
...@@ -28,8 +28,6 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -28,8 +28,6 @@ namespace Titanium.Web.Proxy.EventArguments
/// </summary> /// </summary>
private bool reRequest; private bool reRequest;
internal TaskCompletionSource<bool> ReadHttp2BodyTaskCompletionSource;
/// <summary> /// <summary>
/// Constructor to initialize the proxy /// Constructor to initialize the proxy
/// </summary> /// </summary>
...@@ -99,7 +97,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -99,7 +97,7 @@ namespace Titanium.Web.Proxy.EventArguments
request.ReadHttp2BodyTaskCompletionSource = tcs; request.ReadHttp2BodyTaskCompletionSource = tcs;
// signal to HTTP/2 copy frame method to continue // signal to HTTP/2 copy frame method to continue
ReadHttp2BodyTaskCompletionSource.SetResult(true); request.ReadHttp2BeforeHandlerTaskCompletionSource.SetResult(true);
await tcs.Task; await tcs.Task;
} }
...@@ -165,7 +163,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -165,7 +163,7 @@ namespace Titanium.Web.Proxy.EventArguments
response.ReadHttp2BodyTaskCompletionSource = tcs; response.ReadHttp2BodyTaskCompletionSource = tcs;
// signal to HTTP/2 copy frame method to continue // signal to HTTP/2 copy frame method to continue
ReadHttp2BodyTaskCompletionSource.SetResult(true); response.ReadHttp2BeforeHandlerTaskCompletionSource.SetResult(true);
await tcs.Task; await tcs.Task;
} }
......
...@@ -55,25 +55,7 @@ namespace Titanium.Web.Proxy.EventArguments ...@@ -55,25 +55,7 @@ namespace Titanium.Web.Proxy.EventArguments
HttpClient = new HttpWebClient(request); HttpClient = new HttpWebClient(request);
LocalEndPoint = endPoint; LocalEndPoint = endPoint;
HttpClient.ProcessId = new Lazy<int>(() => HttpClient.ProcessId = new Lazy<int>(() => ProxyClient.Connection.GetProcessId(endPoint));
{
if (RunTime.IsWindows)
{
var remoteEndPoint = ClientEndPoint;
// If client is localhost get the process id
if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
{
var ipVersion = endPoint.IpV6Enabled ? IpVersion.Ipv6 : IpVersion.Ipv4;
return TcpHelper.GetProcessIdByLocalPort(ipVersion, remoteEndPoint.Port);
}
// can't access process Id of remote request from remote machine
return -1;
}
throw new PlatformNotSupportedException();
});
} }
/// <summary> /// <summary>
......
...@@ -50,6 +50,8 @@ namespace Titanium.Web.Proxy.Http ...@@ -50,6 +50,8 @@ namespace Titanium.Web.Proxy.Http
/// </summary> /// </summary>
internal string OriginalContentEncoding { get; set; } internal string OriginalContentEncoding { get; set; }
internal TaskCompletionSource<bool> ReadHttp2BeforeHandlerTaskCompletionSource;
internal TaskCompletionSource<bool> ReadHttp2BodyTaskCompletionSource; internal TaskCompletionSource<bool> ReadHttp2BodyTaskCompletionSource;
internal MemoryStream Http2BodyData; internal MemoryStream Http2BodyData;
......
...@@ -89,7 +89,30 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -89,7 +89,30 @@ namespace Titanium.Web.Proxy.Http2
bool endStream = false; bool endStream = false;
//System.Diagnostics.Debug.WriteLine("CLIENT: " + isClient + ", STREAM: " + streamId + ", TYPE: " + type); SessionEventArgs args = null;
RequestResponseBase rr = null;
if (type == 0 || type == 1)
{
if (!sessions.TryGetValue(streamId, out args))
{
if (type == 0)
{
throw new ProxyHttpException("HTTP Body data received before any header frame.", null, args);
}
if (!isClient)
{
throw new ProxyHttpException("HTTP Response received before any Request header frame.", null, args);
}
args = sessionFactory();
sessions.TryAdd(streamId, args);
}
rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
}
//System.Diagnostics.Debug.WriteLine("CONN: " + connectionId + ", CLIENT: " + isClient + ", STREAM: " + streamId + ", TYPE: " + type);
if (type == 0 /* data */) if (type == 0 /* data */)
{ {
bool endStreamFlag = (flags & (int)Http2FrameFlag.EndStream) != 0; bool endStreamFlag = (flags & (int)Http2FrameFlag.EndStream) != 0;
...@@ -98,12 +121,6 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -98,12 +121,6 @@ namespace Titanium.Web.Proxy.Http2
endStream = true; endStream = true;
} }
if (!sessions.TryGetValue(streamId, out var args))
{
throw new ProxyHttpException("HTTP Body data received before any header frame.", null, args);
}
var rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
if (rr.ReadHttp2BodyTaskCompletionSource != null) if (rr.ReadHttp2BodyTaskCompletionSource != null)
{ {
// Get body method was called in the "before" event handler // Get body method was called in the "before" event handler
...@@ -115,9 +132,15 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -115,9 +132,15 @@ namespace Titanium.Web.Proxy.Http2
{ {
rr.Body = data.ToArray(); rr.Body = data.ToArray();
rr.IsBodyRead = true; rr.IsBodyRead = true;
rr.ReadHttp2BodyTaskCompletionSource.SetResult(true);
var tcs = rr.ReadHttp2BodyTaskCompletionSource;
rr.ReadHttp2BodyTaskCompletionSource = null; rr.ReadHttp2BodyTaskCompletionSource = null;
if (!tcs.Task.IsCompleted)
{
tcs.SetResult(true);
}
rr.Http2BodyData = null; rr.Http2BodyData = null;
} }
} }
...@@ -150,12 +173,6 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -150,12 +173,6 @@ namespace Titanium.Web.Proxy.Http2
dataLength -= buffer[0]; dataLength -= buffer[0];
} }
if (!sessions.TryGetValue(streamId, out var args))
{
args = sessionFactory();
sessions.TryAdd(streamId, args);
}
var headerListener = new MyHeaderListener( var headerListener = new MyHeaderListener(
(name, value) => (name, value) =>
{ {
...@@ -194,17 +211,17 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -194,17 +211,17 @@ namespace Titanium.Web.Proxy.Http2
if (endHeaders) if (endHeaders)
{ {
var handler = onBeforeRequestResponse(args);
var tcs = new TaskCompletionSource<bool>(); var tcs = new TaskCompletionSource<bool>();
args.ReadHttp2BodyTaskCompletionSource = tcs; rr.ReadHttp2BeforeHandlerTaskCompletionSource = tcs;
var handler = onBeforeRequestResponse(args);
if (handler == await Task.WhenAny(handler, tcs.Task)) if (handler == await Task.WhenAny(tcs.Task, handler))
{ {
rr.ReadHttp2BeforeHandlerTaskCompletionSource = null;
tcs.SetResult(true); tcs.SetResult(true);
} }
var rr = isClient ? (RequestResponseBase)args.HttpClient.Request : args.HttpClient.Response;
rr.Locked = true; rr.Locked = true;
} }
} }
...@@ -212,6 +229,7 @@ namespace Titanium.Web.Proxy.Http2 ...@@ -212,6 +229,7 @@ namespace Titanium.Web.Proxy.Http2
if (!isClient && endStream) if (!isClient && endStream)
{ {
sessions.TryRemove(streamId, out _); sessions.TryRemove(streamId, out _);
//System.Diagnostics.Debug.WriteLine("REMOVED CONN: " + connectionId + ", CLIENT: " + isClient + ", STREAM: " + streamId + ", TYPE: " + type);
} }
// do not cancel the write operation // do not cancel the write operation
......
...@@ -7,6 +7,8 @@ using System.Net.Security; ...@@ -7,6 +7,8 @@ using System.Net.Security;
using System.Net.Sockets; using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
using Titanium.Web.Proxy.Extensions; using Titanium.Web.Proxy.Extensions;
using Titanium.Web.Proxy.Helpers;
using Titanium.Web.Proxy.Models;
namespace Titanium.Web.Proxy.Network.Tcp namespace Titanium.Web.Proxy.Network.Tcp
{ {
...@@ -34,11 +36,42 @@ namespace Titanium.Web.Proxy.Network.Tcp ...@@ -34,11 +36,42 @@ namespace Titanium.Web.Proxy.Network.Tcp
private readonly TcpClient tcpClient; private readonly TcpClient tcpClient;
private int? processId;
public Stream GetStream() public Stream GetStream()
{ {
return tcpClient.GetStream(); return tcpClient.GetStream();
} }
public int GetProcessId(ProxyEndPoint endPoint)
{
if (processId.HasValue)
{
return processId.Value;
}
if (RunTime.IsWindows)
{
var remoteEndPoint = (IPEndPoint)RemoteEndPoint;
// If client is localhost get the process id
if (NetworkHelper.IsLocalIpAddress(remoteEndPoint.Address))
{
var ipVersion = endPoint.IpV6Enabled ? IpVersion.Ipv6 : IpVersion.Ipv4;
processId = TcpHelper.GetProcessIdByLocalPort(ipVersion, remoteEndPoint.Port);
}
else
{
// can't access process Id of remote request from remote machine
processId = -1;
}
return processId.Value;
}
throw new PlatformNotSupportedException();
}
/// <summary> /// <summary>
/// Dispose. /// Dispose.
/// </summary> /// </summary>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment