mirror of
https://github.com/aspnet/JavaScriptServices.git
synced 2025-12-24 18:47:30 +00:00
Implement SocketNodeInstance
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
{
|
||||
internal class NamedPipeConnection : StreamConnection
|
||||
{
|
||||
private bool _disposedValue = false;
|
||||
private NamedPipeClientStream _namedPipeClientStream;
|
||||
|
||||
public override async Task<Stream> Open(string address)
|
||||
{
|
||||
_namedPipeClientStream = new NamedPipeClientStream(".", address, PipeDirection.InOut);
|
||||
await _namedPipeClientStream.ConnectAsync().ConfigureAwait(false);
|
||||
return _namedPipeClientStream;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
if (_namedPipeClientStream != null)
|
||||
{
|
||||
_namedPipeClientStream.Dispose();
|
||||
}
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
{
|
||||
internal abstract class StreamConnection : IDisposable
|
||||
{
|
||||
public abstract Task<Stream> Open(string address);
|
||||
public abstract void Dispose();
|
||||
|
||||
public static StreamConnection Create()
|
||||
{
|
||||
var useNamedPipes = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
|
||||
if (useNamedPipes)
|
||||
{
|
||||
return new NamedPipeConnection();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new UnixDomainSocketConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.IO;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
{
|
||||
internal class UnixDomainSocketConnection : StreamConnection
|
||||
{
|
||||
private bool _disposedValue = false;
|
||||
private NetworkStream _networkStream;
|
||||
private Socket _socket;
|
||||
|
||||
public override async Task<Stream> Open(string address)
|
||||
{
|
||||
var endPoint = new UnixDomainSocketEndPoint("/tmp/" + address);
|
||||
_socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Unspecified);
|
||||
await _socket.ConnectAsync(endPoint).ConfigureAwait(false);
|
||||
_networkStream = new NetworkStream(_socket);
|
||||
return _networkStream;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
if (_networkStream != null)
|
||||
{
|
||||
_networkStream.Dispose();
|
||||
}
|
||||
|
||||
if (_socket != null)
|
||||
{
|
||||
_socket.Dispose();
|
||||
}
|
||||
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.AspNetCore.NodeServices.HostingModels.PhysicalConnections
|
||||
{
|
||||
// From System.IO.Pipes/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs (an internal class in System.IO.Pipes)
|
||||
internal sealed class UnixDomainSocketEndPoint : EndPoint
|
||||
{
|
||||
private const AddressFamily EndPointAddressFamily = AddressFamily.Unix;
|
||||
|
||||
private static readonly Encoding s_pathEncoding = Encoding.UTF8;
|
||||
private static readonly int s_nativePathOffset = 2; // = offsetof(struct sockaddr_un, sun_path). It's the same on Linux and OSX
|
||||
private static readonly int s_nativePathLength = 91; // sockaddr_un.sun_path at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_un.h.html, -1 for terminator
|
||||
private static readonly int s_nativeAddressSize = s_nativePathOffset + s_nativePathLength;
|
||||
|
||||
private readonly string _path;
|
||||
private readonly byte[] _encodedPath;
|
||||
|
||||
public UnixDomainSocketEndPoint(string path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(path));
|
||||
}
|
||||
|
||||
_path = path;
|
||||
_encodedPath = s_pathEncoding.GetBytes(_path);
|
||||
|
||||
if (path.Length == 0 || _encodedPath.Length > s_nativePathLength)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(path));
|
||||
}
|
||||
}
|
||||
|
||||
internal UnixDomainSocketEndPoint(SocketAddress socketAddress)
|
||||
{
|
||||
if (socketAddress == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(socketAddress));
|
||||
}
|
||||
|
||||
if (socketAddress.Family != EndPointAddressFamily ||
|
||||
socketAddress.Size > s_nativeAddressSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(socketAddress));
|
||||
}
|
||||
|
||||
if (socketAddress.Size > s_nativePathOffset)
|
||||
{
|
||||
_encodedPath = new byte[socketAddress.Size - s_nativePathOffset];
|
||||
for (int i = 0; i < _encodedPath.Length; i++)
|
||||
{
|
||||
_encodedPath[i] = socketAddress[s_nativePathOffset + i];
|
||||
}
|
||||
|
||||
_path = s_pathEncoding.GetString(_encodedPath, 0, _encodedPath.Length);
|
||||
}
|
||||
else
|
||||
{
|
||||
_encodedPath = Array.Empty<byte>();
|
||||
_path = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public override SocketAddress Serialize()
|
||||
{
|
||||
var result = new SocketAddress(AddressFamily.Unix, s_nativeAddressSize);
|
||||
|
||||
for (int index = 0; index < _encodedPath.Length; index++)
|
||||
{
|
||||
result[s_nativePathOffset + index] = _encodedPath[index];
|
||||
}
|
||||
result[s_nativePathOffset + _encodedPath.Length] = 0; // path must be null-terminated
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public override EndPoint Create(SocketAddress socketAddress) => new UnixDomainSocketEndPoint(socketAddress);
|
||||
|
||||
public override AddressFamily AddressFamily => EndPointAddressFamily;
|
||||
|
||||
public override string ToString() => _path;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user