private static unsafe bool ToIPEndPointStruct(sockaddr_storage *addr, out IPEndPointStruct ep, IPAddress reuseAddress = null) { if (addr->ss_family == AF_INET) { sockaddr_in *addrIn = (sockaddr_in *)addr; long value = ((addrIn->sin_addr.s_addr[3] << 24 | addrIn->sin_addr.s_addr[2] << 16 | addrIn->sin_addr.s_addr[1] << 8 | addrIn->sin_addr.s_addr[0]) & 0x0FFFFFFFF); #pragma warning disable CS0618 // 'IPAddress.Address' is obsolete bool matchesReuseAddress = reuseAddress != null && reuseAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && reuseAddress.Address == value; #pragma warning restore CS0618 int port = ntohs(addrIn->sin_port); ep = new IPEndPointStruct(matchesReuseAddress ? reuseAddress : new IPAddress(value), port); return(true); } else if (addr->ss_family == AF_INET6) { sockaddr_in6 *addrIn = (sockaddr_in6 *)addr; // We can't check if we can use reuseAddress without allocating. const int length = 16; var bytes = new byte[length]; for (int i = 0; i < length; i++) { bytes[i] = addrIn->sin6_addr.s6_addr[i]; } int port = ntohs(addrIn->sin6_port); ep = new IPEndPointStruct(new IPAddress(bytes, addrIn->sin6_scope_id), port); return(true); } else { ep = default(IPEndPointStruct); return(false); } }
internal static unsafe void GetSockaddrInet(IPEndPointStruct inetAddress, sockaddr_storage *addr, out int length) { if (inetAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { sockaddr_in *addrIn = (sockaddr_in *)addr; addrIn->sin_family = AF_INET; addrIn->sin_port = htons((ushort)inetAddress.Port); int bytesWritten; inetAddress.Address.TryWriteBytes(new Span <byte>(addrIn->sin_addr.s_addr, 4), out bytesWritten); length = SizeOf.sockaddr_in; } else if (inetAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6) { sockaddr_in6 *addrIn = (sockaddr_in6 *)addr; addrIn->sin6_family = AF_INET6; addrIn->sin6_port = htons((ushort)inetAddress.Port); addrIn->sin6_flowinfo = 0; addrIn->sin6_scope_id = 0; int bytesWritten; inetAddress.Address.TryWriteBytes(new Span <byte>(addrIn->sin6_addr.s6_addr, 16), out bytesWritten); length = SizeOf.sockaddr_in6; } else { length = 0; } }
public unsafe PosixResult TryBind(IPEndPointStruct endpoint) { sockaddr_storage addr; GetSockaddrInet(endpoint, &addr, out int length); int rv = bind(DangerousGetHandle().ToInt32(), (sockaddr *)&addr, length); return(PosixResult.FromReturnValue(rv)); }
public unsafe PosixResult TryConnect(IPEndPointStruct endpoint) { sockaddr_storage addr; GetSockaddrInet(endpoint, &addr, out int length); int rv; do { rv = connect(DangerousGetHandle().ToInt32(), (sockaddr *)&addr, length); } while (rv < 0 && errno == EINTR); return(PosixResult.FromReturnValue(rv)); }
public unsafe PosixResult TryGetPeerIPAddress(out IPEndPointStruct ep) { IPSocketAddress socketAddress; var rv = SocketInterop.GetPeerName(this, (byte *)&socketAddress, sizeof(IPSocketAddress)); if (rv.IsSuccess) { ep = socketAddress.ToIPEndPoint(); } else { ep = default(IPEndPointStruct); } return(rv); }
public unsafe IPSocketAddress(IPEndPointStruct endPoint) { bool ipv4 = endPoint.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork; FlowInfo = 0; _family = (short)(ipv4 ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6); ScopeId = ipv4 ? 0 : (uint)endPoint.Address.ScopeId; Port = (ushort)endPoint.Port; var bytes = endPoint.Address.GetAddressBytes(); fixed(byte *address = Address) { for (int i = 0; i < (ipv4 ? 4 : 16); i++) { address[i] = bytes[i]; } } }
public static unsafe PosixResult TryGetPeerIPAddress(int socket, out IPEndPointStruct ep, IPAddress reuseAddress = null) { sockaddr_storage socketAddress; var rv = SocketInterop.GetPeerName(socket, &socketAddress); if (rv.IsSuccess) { if (!ToIPEndPointStruct(&socketAddress, out ep, reuseAddress)) { return(new PosixResult(PosixResult.EINVAL)); } } else { ep = default(IPEndPointStruct); } return(rv); }
private int HandleAccept(TSocket tacceptSocket) { var type = tacceptSocket.Type; int clientFd = -1; PosixResult result; if (type == SocketFlags.TypeAccept) { // TODO: should we handle more than 1 accept? If we do, we shouldn't be to eager // as that might give the kernel the impression we have nothing to do // which could interfere with the SO_REUSEPORT load-balancing. result = tacceptSocket.TryAccept(out clientFd, blocking: false); } else { result = tacceptSocket.TryReceiveSocket(out clientFd, blocking: false); if (result.Value == 0) { // The socket passing us file descriptors has closed. // We dispose our end so we get get removed from the epoll. tacceptSocket.Close(); return(0); } } if (result.IsSuccess) { TSocket tsocket; try { SocketFlags flags = SocketFlags.TypeClient | (tacceptSocket.IsDeferSend ? SocketFlags.DeferSend : SocketFlags.None); tsocket = new TSocket(this, clientFd, flags) { ZeroCopyThreshold = tacceptSocket.ZeroCopyThreshold }; bool ipSocket = !object.ReferenceEquals(tacceptSocket.LocalAddress, NotIPSocket); // Store the last LocalAddress on the tacceptSocket so we might reuse it instead // of allocating a new one for the same address. IPEndPointStruct localAddress = default(IPEndPointStruct); IPEndPointStruct remoteAddress = default(IPEndPointStruct); if (ipSocket && tsocket.TryGetLocalIPAddress(out localAddress, tacceptSocket.LocalAddress)) { tsocket.LocalAddress = localAddress.Address; tsocket.LocalPort = localAddress.Port; if (tsocket.TryGetPeerIPAddress(out remoteAddress)) { tsocket.RemoteAddress = remoteAddress.Address; tsocket.RemotePort = remoteAddress.Port; } } else { // This is not an IP socket. tacceptSocket.LocalAddress = NotIPSocket; ipSocket = false; } if (ipSocket) { tsocket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1); } } catch { IOInterop.Close(clientFd); return(0); } tsocket.MiddlewareTask = _connectionDispatcher.OnConnection(tsocket); lock (_sockets) { _sockets.Add(clientFd, tsocket); } bool dataMayBeAvailable = tacceptSocket.IsDeferAccept; tsocket.Start(dataMayBeAvailable); return(1); } else { return(0); } }
public unsafe PosixResult TryGetPeerIPAddress(out IPEndPointStruct ep) => SocketInterop.TryGetPeerIPAddress(this, out ep);
public unsafe PosixResult TryGetLocalIPAddress(out IPEndPointStruct ep, IPAddress reuseAddress = null) => SocketInterop.TryGetLocalIPAddress(this, out ep, reuseAddress);
public void Connect(IPEndPointStruct endpoint) { TryConnect(endpoint) .ThrowOnError(); }
public void Bind(IPEndPointStruct endpoint) { TryBind(endpoint) .ThrowOnError(); }
public static unsafe PosixResult TryGetPeerIPAddress(Socket socket, out IPEndPointStruct ep, IPAddress reuseAddress = null) => TryGetPeerIPAddress(socket.DangerousGetHandle().ToInt32(), out ep, reuseAddress);
private int HandleAccept(TSocket tacceptSocket) { var type = tacceptSocket.Type; int clientFd = -1; PosixResult result; if (type == SocketFlags.TypeAccept) { // TODO: should we handle more than 1 accept? If we do, we shouldn't be to eager // as that might give the kernel the impression we have nothing to do // which could interfere with the SO_REUSEPORT load-balancing. result = tacceptSocket.TryAccept(out clientFd, blocking: false); } else { result = tacceptSocket.TryReceiveSocket(out clientFd, blocking: false); if (result.Value == 0) { // The socket passing us file descriptors has closed. // We dispose our end so we get get removed from the epoll. tacceptSocket.Close(); return(0); } } if (result.IsSuccess) { TSocket tsocket; try { SocketFlags flags = SocketFlags.TypeClient | (tacceptSocket.IsDeferSend ? SocketFlags.DeferSend : SocketFlags.None); tsocket = new TSocket(this, clientFd, flags, _transportOptions) { ZeroCopyThreshold = tacceptSocket.ZeroCopyThreshold }; var localIpEndPoint = tacceptSocket.LocalEndPoint as IPEndPoint; bool ipSocket = !object.ReferenceEquals(localIpEndPoint?.Address, NotIPSocket); // Store the last LocalAddress on the tacceptSocket so we might reuse it instead // of allocating a new one for the same address. IPEndPointStruct localAddress = default(IPEndPointStruct); IPEndPointStruct remoteAddress = default(IPEndPointStruct); if (ipSocket && tsocket.TryGetLocalIPAddress(out localAddress, localIpEndPoint?.Address)) { tsocket.LocalEndPoint = new IPEndPoint(localAddress.Address, localAddress.Port); if (tsocket.TryGetPeerIPAddress(out remoteAddress)) { tsocket.RemoteEndPoint = new IPEndPoint(remoteAddress.Address, remoteAddress.Port); } } else { // This is not an IP socket. // REVIEW: Should LocalEndPoint be null instead? Some other EndPoint type? tacceptSocket.LocalEndPoint = new IPEndPoint(NotIPSocket, 0); ipSocket = false; } if (ipSocket) { tsocket.SetSocketOption(SOL_TCP, TCP_NODELAY, 1); } } catch { IOInterop.Close(clientFd); return(0); } bool accepted = _acceptQueue.Writer.TryWrite(tsocket); Debug.Assert(accepted, "The connection was not written to the channel!"); lock (_sockets) { _sockets.Add(clientFd, tsocket); } bool dataMayBeAvailable = tacceptSocket.IsDeferAccept; tsocket.Start(dataMayBeAvailable); return(1); } else { return(0); } }
public unsafe PosixResult TryConnect(IPEndPointStruct endpoint) { IPSocketAddress socketAddress = new IPSocketAddress(endpoint); return(SocketInterop.Connect(this, (byte *)&socketAddress, sizeof(IPSocketAddress))); }