Skip to content
This repository was archived by the owner on Dec 18, 2018. It is now read-only.

Record remote IPAddress and port #284

Merged
merged 1 commit into from
Oct 29, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions samples/SampleApp/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IAp
context.Request.Path,
context.Request.QueryString);

var connectionFeature = context.Connection;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think Connection will ever be null, but the addresses may be.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the null check be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

Console.WriteLine($"Peer: {connectionFeature.RemoteIpAddress?.ToString()} {connectionFeature.RemotePort}");
Console.WriteLine($"Sock: {connectionFeature.LocalIpAddress?.ToString()} {connectionFeature.LocalPort}");
Console.WriteLine($"IsLocal: {connectionFeature.IsLocal}");

context.Response.ContentLength = 11;
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("Hello world");
Expand Down
20 changes: 18 additions & 2 deletions src/Microsoft.AspNet.Server.Kestrel/Http/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Net;
using System.Threading;
using Microsoft.AspNet.Server.Kestrel.Filter;
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
Expand All @@ -28,6 +29,9 @@ public class Connection : ConnectionContext, IConnectionControl
private readonly object _stateLock = new object();
private ConnectionState _connectionState;

private IPEndPoint _remoteEndPoint;
private IPEndPoint _localEndPoint;

public Connection(ListenerContext context, UvStreamHandle socket) : base(context)
{
_socket = socket;
Expand All @@ -46,13 +50,20 @@ public void Start()
// Start socket prior to applying the ConnectionFilter
_socket.ReadStart(_allocCallback, _readCallback, this);

var tcpHandle = _socket as UvTcpHandle;
if (tcpHandle != null)
{
_remoteEndPoint = tcpHandle.GetPeerIPEndPoint();
_localEndPoint = tcpHandle.GetSockIPEndPoint();
}

// Don't initialize _frame until SocketInput and SocketOutput are set to their final values.
if (ConnectionFilter == null)
{
SocketInput = _rawSocketInput;
SocketOutput = _rawSocketOutput;

_frame = new Frame(this);
_frame = CreateFrame();
_frame.Start();
}
else
Expand Down Expand Up @@ -94,7 +105,7 @@ private void ApplyConnectionFilter()
SocketInput = filteredStreamAdapter.SocketInput;
SocketOutput = filteredStreamAdapter.SocketOutput;

_frame = new Frame(this);
_frame = CreateFrame();
_frame.Start();
}

Expand Down Expand Up @@ -142,6 +153,11 @@ private void OnRead(UvStreamHandle handle, int status)
_rawSocketInput.IncomingComplete(readCount, error);
}

private Frame CreateFrame()
{
return new Frame(this, _remoteEndPoint, _localEndPoint);
}

void IConnectionControl.Pause()
{
Log.ConnectionPause(_connectionId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.Extensions.Primitives;

namespace Microsoft.AspNet.Server.Kestrel.Http
{
public partial class Frame : IFeatureCollection, IHttpRequestFeature, IHttpResponseFeature, IHttpUpgradeFeature
public partial class Frame : IFeatureCollection,
IHttpRequestFeature,
IHttpResponseFeature,
IHttpUpgradeFeature,
IHttpConnectionFeature
{
// NOTE: When feature interfaces are added to or removed from this Frame class implementation,
// then the list of `implementedFeatures` in the generated code project MUST also be updated.
Expand Down Expand Up @@ -246,6 +251,16 @@ bool IHttpUpgradeFeature.IsUpgradableRequest

int IFeatureCollection.Revision => _featureRevision;

IPAddress IHttpConnectionFeature.RemoteIpAddress { get; set; }

IPAddress IHttpConnectionFeature.LocalIpAddress { get; set; }

int IHttpConnectionFeature.RemotePort { get; set; }

int IHttpConnectionFeature.LocalPort { get; set; }

bool IHttpConnectionFeature.IsLocal { get; set; }

object IFeatureCollection.this[Type key]
{
get { return FastFeatureGet(key); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ private void FastReset()
_currentIHttpRequestFeature = this;
_currentIHttpResponseFeature = this;
_currentIHttpUpgradeFeature = this;
_currentIHttpConnectionFeature = this;

_currentIHttpRequestIdentifierFeature = null;
_currentIServiceProvidersFeature = null;
_currentIHttpRequestLifetimeFeature = null;
_currentIHttpConnectionFeature = null;
_currentIHttpAuthenticationFeature = null;
_currentIQueryFeature = null;
_currentIFormFeature = null;
Expand Down
41 changes: 36 additions & 5 deletions src/Microsoft.AspNet.Server.Kestrel/Http/Frame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Server.Kestrel.Infrastructure;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
Expand Down Expand Up @@ -44,8 +46,22 @@ public partial class Frame : FrameContext, IFrameControl
private bool _autoChunk;
private Exception _applicationException;

public Frame(ConnectionContext context) : base(context)
private readonly IPEndPoint _localEndPoint;
private readonly IPEndPoint _remoteEndPoint;

public Frame(ConnectionContext context)
: this(context, remoteEndPoint: null, localEndPoint: null)
{
}

public Frame(ConnectionContext context,
IPEndPoint remoteEndPoint,
IPEndPoint localEndPoint)
: base(context)
{
_remoteEndPoint = remoteEndPoint;
_localEndPoint = localEndPoint;

FrameControl = this;
Reset();
}
Expand Down Expand Up @@ -99,6 +115,21 @@ public void Reset()
ResponseBody = null;
DuplexStream = null;

var httpConnectionFeature = this as IHttpConnectionFeature;
httpConnectionFeature.RemoteIpAddress = _remoteEndPoint?.Address;
httpConnectionFeature.RemotePort = _remoteEndPoint?.Port ?? 0;

httpConnectionFeature.LocalIpAddress = _localEndPoint?.Address;
httpConnectionFeature.LocalPort = _localEndPoint?.Port ?? 0;

if (_remoteEndPoint != null && _localEndPoint != null)
{
httpConnectionFeature.IsLocal = _remoteEndPoint.Address.Equals(_localEndPoint.Address);
}
else
{
httpConnectionFeature.IsLocal = false;
}
}

public void ResetResponseHeaders()
Expand All @@ -123,7 +154,7 @@ public void Start()
/// <summary>
/// Should be called when the server wants to initiate a shutdown. The Task returned will
/// become complete when the RequestProcessingAsync function has exited. It is expected that
/// Stop will be called on all active connections, and Task.WaitAll() will be called on every
/// Stop will be called on all active connections, and Task.WaitAll() will be called on every
/// return value.
/// </summary>
public Task Stop()
Expand All @@ -136,7 +167,7 @@ public Task Stop()
}

/// <summary>
/// Primary loop which consumes socket input, parses it for protocol framing, and invokes the
/// Primary loop which consumes socket input, parses it for protocol framing, and invokes the
/// application delegate for as long as the socket is intended to remain open.
/// The resulting Task from this loop is preserved in a field which is used when the server needs
/// to drain and close all currently active connections.
Expand Down Expand Up @@ -731,7 +762,7 @@ public static bool TakeMessageHeaders(SocketInput input, FrameRequestHeaders req

if (chSecond != '\n')
{
// "\r" was all by itself, move just after it and try again
// "\r" was all by itself, move just after it and try again
scan = endValue;
scan.Take();
continue;
Expand All @@ -740,7 +771,7 @@ public static bool TakeMessageHeaders(SocketInput input, FrameRequestHeaders req
var chThird = scan.Peek();
if (chThird == ' ' || chThird == '\t')
{
// special case, "\r\n " or "\r\n\t".
// special case, "\r\n " or "\r\n\t".
// this is considered wrapping"linear whitespace" and is actually part of the header value
// continue past this for the next
wrapping = true;
Expand Down
67 changes: 42 additions & 25 deletions src/Microsoft.AspNet.Server.Kestrel/Networking/Libuv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public Libuv()
_uv_req_size = NativeDarwinMonoMethods.uv_req_size;
_uv_ip4_addr = NativeDarwinMonoMethods.uv_ip4_addr;
_uv_ip6_addr = NativeDarwinMonoMethods.uv_ip6_addr;
_uv_tcp_getpeername = NativeDarwinMonoMethods.uv_tcp_getpeername;
_uv_tcp_getsockname = NativeDarwinMonoMethods.uv_tcp_getsockname;
_uv_walk = NativeDarwinMonoMethods.uv_walk;
}
else
Expand Down Expand Up @@ -95,6 +97,8 @@ public Libuv()
_uv_req_size = NativeMethods.uv_req_size;
_uv_ip4_addr = NativeMethods.uv_ip4_addr;
_uv_ip6_addr = NativeMethods.uv_ip6_addr;
_uv_tcp_getpeername = NativeMethods.uv_tcp_getpeername;
_uv_tcp_getsockname = NativeMethods.uv_tcp_getsockname;
_uv_walk = NativeMethods.uv_walk;
}
}
Expand Down Expand Up @@ -206,9 +210,9 @@ public void tcp_init(UvLoopHandle loop, UvTcpHandle handle)
Check(_uv_tcp_init(loop, handle));
}

protected delegate int uv_tcp_bind_func(UvTcpHandle handle, ref sockaddr addr, int flags);
protected delegate int uv_tcp_bind_func(UvTcpHandle handle, ref SockAddr addr, int flags);
protected uv_tcp_bind_func _uv_tcp_bind;
public void tcp_bind(UvTcpHandle handle, ref sockaddr addr, int flags)
public void tcp_bind(UvTcpHandle handle, ref SockAddr addr, int flags)
{
handle.Validate();
Check(_uv_tcp_bind(handle, ref addr, flags));
Expand Down Expand Up @@ -365,16 +369,16 @@ public int req_size(RequestType reqType)
return _uv_req_size(reqType);
}

protected delegate int uv_ip4_addr_func(string ip, int port, out sockaddr addr);
protected delegate int uv_ip4_addr_func(string ip, int port, out SockAddr addr);
protected uv_ip4_addr_func _uv_ip4_addr;
public int ip4_addr(string ip, int port, out sockaddr addr, out Exception error)
public int ip4_addr(string ip, int port, out SockAddr addr, out Exception error)
{
return Check(_uv_ip4_addr(ip, port, out addr), out error);
}

protected delegate int uv_ip6_addr_func(string ip, int port, out sockaddr addr);
protected delegate int uv_ip6_addr_func(string ip, int port, out SockAddr addr);
protected uv_ip6_addr_func _uv_ip6_addr;
public int ip6_addr(string ip, int port, out sockaddr addr, out Exception error)
public int ip6_addr(string ip, int port, out SockAddr addr, out Exception error)
{
return Check(_uv_ip6_addr(ip, port, out addr), out error);
}
Expand All @@ -388,24 +392,25 @@ unsafe public void walk(UvLoopHandle loop, uv_walk_cb walk_cb, IntPtr arg)
_uv_walk(loop, walk_cb, arg);
}

public uv_buf_t buf_init(IntPtr memory, int len)
public delegate int uv_tcp_getsockname_func(UvTcpHandle handle, out SockAddr addr, ref int namelen);
protected uv_tcp_getsockname_func _uv_tcp_getsockname;
public void tcp_getsockname(UvTcpHandle handle, out SockAddr addr, ref int namelen)
{
return new uv_buf_t(memory, len, IsWindows);
handle.Validate();
Check(_uv_tcp_getsockname(handle, out addr, ref namelen));
}

public struct sockaddr
public delegate int uv_tcp_getpeername_func(UvTcpHandle handle, out SockAddr addr, ref int namelen);
protected uv_tcp_getpeername_func _uv_tcp_getpeername;
public void tcp_getpeername(UvTcpHandle handle, out SockAddr addr, ref int namelen)
{
// this type represents native memory occupied by sockaddr struct
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms740496(v=vs.85).aspx
// although the c/c++ header defines it as a 2-byte short followed by a 14-byte array,
// the simplest way to reserve the same size in c# is with four nameless long values

private long _field0;
private long _field1;
private long _field2;
private long _field3;
handle.Validate();
Check(_uv_tcp_getpeername(handle, out addr, ref namelen));
}

public sockaddr(long ignored) { _field3 = _field0 = _field1 = _field2 = _field3 = 0; }
public uv_buf_t buf_init(IntPtr memory, int len)
{
return new uv_buf_t(memory, len, IsWindows);
}

public struct uv_buf_t
Expand Down Expand Up @@ -504,7 +509,7 @@ private static class NativeMethods
public static extern int uv_tcp_init(UvLoopHandle loop, UvTcpHandle handle);

[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_tcp_bind(UvTcpHandle handle, ref sockaddr addr, int flags);
public static extern int uv_tcp_bind(UvTcpHandle handle, ref SockAddr addr, int flags);

[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_tcp_open(UvTcpHandle handle, IntPtr hSocket);
Expand Down Expand Up @@ -564,10 +569,16 @@ private static class NativeMethods
public static extern int uv_req_size(RequestType reqType);

[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_ip4_addr(string ip, int port, out sockaddr addr);
public static extern int uv_ip4_addr(string ip, int port, out SockAddr addr);

[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_ip6_addr(string ip, int port, out sockaddr addr);
public static extern int uv_ip6_addr(string ip, int port, out SockAddr addr);

[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_tcp_getsockname(UvTcpHandle handle, out SockAddr name, ref int namelen);

[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_tcp_getpeername(UvTcpHandle handle, out SockAddr name, ref int namelen);

[DllImport("libuv", CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern int uv_walk(UvLoopHandle loop, uv_walk_cb walk_cb, IntPtr arg);
Expand Down Expand Up @@ -606,7 +617,7 @@ private static class NativeDarwinMonoMethods
public static extern int uv_tcp_init(UvLoopHandle loop, UvTcpHandle handle);

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_tcp_bind(UvTcpHandle handle, ref sockaddr addr, int flags);
public static extern int uv_tcp_bind(UvTcpHandle handle, ref SockAddr addr, int flags);

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_tcp_open(UvTcpHandle handle, IntPtr hSocket);
Expand Down Expand Up @@ -666,10 +677,16 @@ private static class NativeDarwinMonoMethods
public static extern int uv_req_size(RequestType reqType);

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_ip4_addr(string ip, int port, out sockaddr addr);
public static extern int uv_ip4_addr(string ip, int port, out SockAddr addr);

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_ip6_addr(string ip, int port, out SockAddr addr);

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_tcp_getsockname(UvTcpHandle handle, out SockAddr name, ref int namelen);

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
public static extern int uv_ip6_addr(string ip, int port, out sockaddr addr);
public static extern int uv_tcp_getpeername(UvTcpHandle handle, out SockAddr name, ref int namelen);

[DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
unsafe public static extern int uv_walk(UvLoopHandle loop, uv_walk_cb walk_cb, IntPtr arg);
Expand Down
Loading