private void bind(IPEndPoint endpoint, int backlog) { Sockaddr servaddr = new SockaddrIn() { sa_family = UnixAddressFamily.AF_INET, sin_family = UnixAddressFamily.AF_INET, sin_addr = new InAddr() { s_addr = BitConverter.ToUInt32(endpoint.Address.GetAddressBytes(), 0) }, sin_port = Syscall.htons((ushort)endpoint.Port) }; // Bind so we are attached var ret = Syscall.bind(listenerSocket, servaddr); if (ret < 0) { throw new IOException($"Failed to bind to endpoint: {Stdlib.GetLastError()}"); } // start listening ret = Syscall.listen(listenerSocket, backlog); if (ret < 0) { throw new IOException($"Failed to set socket to listen: {Stdlib.GetLastError()}"); } }
public void SockaddrInTest() { var address1 = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons(5678), sin_addr = NativeConvert.ToInAddr(IPAddress.Loopback), }; var storage = address1.ToSockaddrStorage(); var address2 = SockaddrIn.FromSockaddrStorage(storage); Assert.AreEqual(address1, address2); var sockaddr = Sockaddr.FromSockaddrStorage(storage); Assert.AreEqual(sockaddr.sa_family, address1.sa_family); var storage2 = storage.ToSockaddrStorage(); Assert.AreEqual(storage, storage2); var storage3 = new SockaddrStorage(123); storage2.CopyTo(storage3); Assert.AreEqual(storage, storage3); Assert.AreEqual("{sin_family=AF_INET, sin_port=htons(5678), sin_addr=127.0.0.1}", address1.ToString()); }
public void IPv6() { if (!Socket.OSSupportsIPv6) { Assert.Ignore("OS does not support IPv6."); } var address = new SockaddrIn6 { sin6_family = UnixAddressFamily.AF_INET6, sin6_port = Syscall.htons(0), sin6_addr = NativeConvert.ToIn6Addr(IPAddress.IPv6Loopback), }; WithSockets(UnixAddressFamily.AF_INET6, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => { if (Syscall.bind(so1, address) < 0) { UnixMarshal.ThrowExceptionForLastError(); } var address1Stor = new SockaddrStorage(); if (Syscall.getsockname(so1, address1Stor) < 0) { UnixMarshal.ThrowExceptionForLastError(); } var address1 = new SockaddrIn6(); address1Stor.CopyTo(address1); // Check getsockname(socket, null) if (Syscall.getsockname(so1, null) < 0) { UnixMarshal.ThrowExceptionForLastError(); } var address2 = new SockaddrIn6(); if (Syscall.getsockname(so1, address2) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(address1, address2); Assert.IsTrue(Syscall.ntohs(address1.sin6_port) != 0); address1.sin6_port = 0; Assert.AreEqual(address, address1); var address3 = new Sockaddr(); if (Syscall.getsockname(so1, address3) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(address.sa_family, address3.sa_family); // Try to store a sockaddr_in6 into a Sockaddr. Should fail because sockaddr_in6 should be larger than sockaddr_in var address4 = new SockaddrIn(); if (Syscall.getsockname(so1, address4) == 0) { Assert.Fail("getsockname() should have failed"); } Assert.AreEqual(Errno.ENOBUFS, Stdlib.GetLastError()); }); }
[ExpectedException(typeof(ArgumentOutOfRangeException))] // IPPROTO_UDP not supported #endif public void SendToRecvFrom() { WithSockets(UnixAddressFamily.AF_INET, UnixSocketType.SOCK_DGRAM, UnixSocketProtocol.IPPROTO_UDP, (so1, so2) => { // Bind UDP socket so1 to 127.0.0.1 with dynamic port var address = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons(0), sin_addr = new InAddr(127, 0, 0, 1) }; if (Syscall.bind(so1, address) < 0) { UnixMarshal.ThrowExceptionForLastError(); } // Get actual port number using getsockname() var actualAddress = new SockaddrIn(); if (Syscall.getsockname(so1, actualAddress) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(actualAddress.sa_family, UnixAddressFamily.AF_INET); var port = Syscall.ntohs(actualAddress.sin_port); Assert.IsTrue(port != 0); var remoteAddress = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons(port), sin_addr = new InAddr(127, 0, 0, 1), }; // Send and receive a few bytes long ret; var buffer1 = new byte[] { 42, 43, 44 }; ret = Syscall.sendto(so2, buffer1, (ulong)buffer1.Length, 0, remoteAddress); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } var senderAddress = new SockaddrIn(); var buffer2 = new byte[1024]; ret = Syscall.recvfrom(so1, buffer2, (ulong)buffer2.Length, 0, senderAddress); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(senderAddress.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual(senderAddress.sin_addr, new InAddr(127, 0, 0, 1)); Assert.AreEqual(buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer2[i]); } }); }
private unsafe static void Connect(IntPtr socket, IPEndPoint ipEndPoint) { var endPointAddressBytes = ipEndPoint.Address.GetAddressBytes(); var inAddress = new InAddr(endPointAddressBytes); var sa = new SockaddrIn { sin_family = AddressFamilies.AF_INET, sin_port = WinSock.htons((ushort)ipEndPoint.Port), sin_addr = inAddress }; var errorCode = WinSock.connect(socket, ref sa, sizeof(SockaddrIn)); if (errorCode == WinSock.Consts.SOCKET_ERROR) { WinSock.ThrowLastWsaError(); } }
/// <summary> /// Waits for a connection and accepts the socket /// </summary> /// <returns>The socket and endpoint.</returns> /// <param name="cancellationToken">Cancellation token.</param> public Task <KeyValuePair <long, EndPoint> > AcceptAsync(CancellationToken cancellationToken) { // TODO: Support the cancellationToken return(Task.Run(() => { var addr = new SockaddrIn(); var ret = Syscall.accept(m_socket, addr); if (ret < 0) { throw new IOException($"Failed to accept: {Stdlib.GetLastError()}"); } // Dummy endpoint var endpoint = new IPEndPoint(IPAddress.Any, 0); // If we get a real endpoint, use that if (addr is SockaddrIn sain) { endpoint = new IPEndPoint((long)sain.sin_addr.s_addr, sain.sin_port); } return new KeyValuePair <long, EndPoint>(ret, endpoint); })); }
private static unsafe bool Bind(IntPtr listeningSocket, int listeningPort) { var endPointAddressBytes = IPAddress.Any.GetAddressBytes(); var inAddress = new InAddr(endPointAddressBytes); var sa = new SockaddrIn { sin_family = AddressFamilies.AF_INET, sin_port = WinSock.htons((ushort)listeningPort), sin_addr = inAddress }; var errorCode = WinSock.bind(listeningSocket, ref sa, sizeof(SockaddrIn)); if (errorCode == WinSock.Consts.SOCKET_ERROR) { WinSock.ThrowLastWsaError(); return(false); } return(true); }
public unsafe void SendMsgRecvMsgAddress () { WithSockets (UnixAddressFamily.AF_INET, UnixSocketType.SOCK_DGRAM, UnixSocketProtocol.IPPROTO_UDP, (so1, so2) => { // Bind UDP socket so1 to 127.0.0.1 with dynamic port var address = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons (0), sin_addr = new InAddr (127, 0, 0, 1), }; if (Syscall.bind (so1, address) < 0) UnixMarshal.ThrowExceptionForLastError (); // Get actual port number using getsockname() var actualAddress = new SockaddrIn (); if (Syscall.getsockname (so1, actualAddress) < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (actualAddress.sa_family, UnixAddressFamily.AF_INET); var port = Syscall.ntohs (actualAddress.sin_port); Assert.IsTrue (port != 0); var remoteAddress = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons (port), sin_addr = new InAddr (127, 0, 0, 1), }; // Send and receive a few bytes long ret; var buffer1 = new byte[] { 42, 43, 44 }; fixed (byte* ptr_buffer1 = buffer1) { var iovecs1 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer1, iov_len = (ulong) buffer1.Length, }, }; var msghdr1 = new Msghdr { msg_name = remoteAddress, msg_iov = iovecs1, msg_iovlen = 1, }; ret = Syscall.sendmsg (so2, msghdr1, 0); msghdr1.msg_name = remoteAddress.ToSockaddrStorage (); if (ret >= 0) ret = Syscall.sendmsg (so2, msghdr1, 0); } if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); var senderAddress = new SockaddrIn (); var senderAddressStorage = new SockaddrStorage (); var buffer2 = new byte[1024]; var buffer3 = new byte[1024]; fixed (byte* ptr_buffer2 = buffer2, ptr_buffer3 = buffer3) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr) ptr_buffer2, iov_len = (ulong) buffer2.Length, }, }; var msghdr2 = new Msghdr { msg_name = senderAddress, msg_iov = iovecs2, msg_iovlen = 1, }; ret = Syscall.recvmsg (so1, msghdr2, 0); msghdr2.msg_name = senderAddressStorage; iovecs2[0].iov_base = (IntPtr) ptr_buffer3; if (ret >= 0) ret = Syscall.recvmsg (so1, msghdr2, 0); } if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (senderAddress.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual (senderAddress.sin_addr, new InAddr (127, 0, 0, 1)); var senderAddress2 = SockaddrIn.FromSockaddrStorage (senderAddressStorage); Assert.AreEqual (senderAddress2.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual (senderAddress2.sin_addr, new InAddr (127, 0, 0, 1)); Assert.AreEqual (buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer2[i]); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer3[i]); }); }
public void SendToRecvFrom () { WithSockets (UnixAddressFamily.AF_INET, UnixSocketType.SOCK_DGRAM, UnixSocketProtocol.IPPROTO_UDP, (so1, so2) => { // Bind UDP socket so1 to 127.0.0.1 with dynamic port var address = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons (0), sin_addr = new InAddr (127, 0, 0, 1) }; if (Syscall.bind (so1, address) < 0) UnixMarshal.ThrowExceptionForLastError (); // Get actual port number using getsockname() var actualAddress = new SockaddrIn (); if (Syscall.getsockname (so1, actualAddress) < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (actualAddress.sa_family, UnixAddressFamily.AF_INET); var port = Syscall.ntohs (actualAddress.sin_port); Assert.IsTrue (port != 0); var remoteAddress = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons (port), sin_addr = new InAddr (127, 0, 0, 1), }; // Send and receive a few bytes long ret; var buffer1 = new byte[] { 42, 43, 44 }; ret = Syscall.sendto (so2, buffer1, (ulong) buffer1.Length, 0, remoteAddress); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); var senderAddress = new SockaddrIn (); var buffer2 = new byte[1024]; ret = Syscall.recvfrom (so1, buffer2, (ulong) buffer2.Length, 0, senderAddress); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (senderAddress.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual (senderAddress.sin_addr, new InAddr (127, 0, 0, 1)); Assert.AreEqual (buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer2[i]); }); }
public void IPv6 () { if (!Socket.OSSupportsIPv6) Assert.Ignore ("OS does not support IPv6."); var address = new SockaddrIn6 { sin6_family = UnixAddressFamily.AF_INET6, sin6_port = Syscall.htons (0), sin6_addr = NativeConvert.ToIn6Addr (IPAddress.IPv6Loopback), }; WithSockets (UnixAddressFamily.AF_INET6, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => { if (Syscall.bind (so1, address) < 0) UnixMarshal.ThrowExceptionForLastError (); var address1Stor = new SockaddrStorage (); if (Syscall.getsockname (so1, address1Stor) < 0) UnixMarshal.ThrowExceptionForLastError (); var address1 = new SockaddrIn6 (); address1Stor.CopyTo (address1); // Check getsockname(socket, null) if (Syscall.getsockname (so1, null) < 0) UnixMarshal.ThrowExceptionForLastError (); var address2 = new SockaddrIn6 (); if (Syscall.getsockname (so1, address2) < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (address1, address2); Assert.IsTrue (Syscall.ntohs (address1.sin6_port) != 0); address1.sin6_port = 0; Assert.AreEqual (address, address1); var address3 = new Sockaddr (); if (Syscall.getsockname (so1, address3) < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (address.sa_family, address3.sa_family); // Try to store a sockaddr_in6 into a Sockaddr. Should fail because sockaddr_in6 should be larger than sockaddr_in var address4 = new SockaddrIn (); if (Syscall.getsockname (so1, address4) == 0) Assert.Fail ("getsockname() should have failed"); Assert.AreEqual (Errno.ENOBUFS, Stdlib.GetLastError ()); }); }
public void SockaddrInTest () { var address1 = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons (5678), sin_addr = NativeConvert.ToInAddr (IPAddress.Loopback), }; var storage = address1.ToSockaddrStorage (); var address2 = SockaddrIn.FromSockaddrStorage (storage); Assert.AreEqual (address1, address2); var sockaddr = Sockaddr.FromSockaddrStorage (storage); Assert.AreEqual (sockaddr.sa_family, address1.sa_family); var storage2 = storage.ToSockaddrStorage (); Assert.AreEqual (storage, storage2); var storage3 = new SockaddrStorage (123); storage2.CopyTo (storage3); Assert.AreEqual (storage, storage3); Assert.AreEqual ("{sin_family=AF_INET, sin_port=htons(5678), sin_addr=127.0.0.1}", address1.ToString ()); }
private static extern int FromSockaddrIn (SockaddrIn source, IntPtr destination);
public static bool TryCopy (SockaddrIn source, IntPtr destination) { return FromSockaddrIn (source, destination) == 0; }
[ExpectedException(typeof(ArgumentOutOfRangeException))] // IPPROTO_UDP not supported #endif public unsafe void SendMsgRecvMsgAddress() { WithSockets(UnixAddressFamily.AF_INET, UnixSocketType.SOCK_DGRAM, UnixSocketProtocol.IPPROTO_UDP, (so1, so2) => { // Bind UDP socket so1 to 127.0.0.1 with dynamic port var address = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons(0), sin_addr = new InAddr(127, 0, 0, 1), }; if (Syscall.bind(so1, address) < 0) { UnixMarshal.ThrowExceptionForLastError(); } // Get actual port number using getsockname() var actualAddress = new SockaddrIn(); if (Syscall.getsockname(so1, actualAddress) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(actualAddress.sa_family, UnixAddressFamily.AF_INET); var port = Syscall.ntohs(actualAddress.sin_port); Assert.IsTrue(port != 0); var remoteAddress = new SockaddrIn { sin_family = UnixAddressFamily.AF_INET, sin_port = Syscall.htons(port), sin_addr = new InAddr(127, 0, 0, 1), }; // Send and receive a few bytes long ret; var buffer1 = new byte[] { 42, 43, 44 }; fixed(byte *ptr_buffer1 = buffer1) { var iovecs1 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer1, iov_len = (ulong)buffer1.Length, }, }; var msghdr1 = new Msghdr { msg_name = remoteAddress, msg_iov = iovecs1, msg_iovlen = 1, }; ret = Syscall.sendmsg(so2, msghdr1, 0); msghdr1.msg_name = remoteAddress.ToSockaddrStorage(); if (ret >= 0) { ret = Syscall.sendmsg(so2, msghdr1, 0); } } if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } var senderAddress = new SockaddrIn(); var senderAddressStorage = new SockaddrStorage(); var buffer2 = new byte[1024]; var buffer3 = new byte[1024]; fixed(byte *ptr_buffer2 = buffer2, ptr_buffer3 = buffer3) { var iovecs2 = new Iovec[] { new Iovec { iov_base = (IntPtr)ptr_buffer2, iov_len = (ulong)buffer2.Length, }, }; var msghdr2 = new Msghdr { msg_name = senderAddress, msg_iov = iovecs2, msg_iovlen = 1, }; ret = Syscall.recvmsg(so1, msghdr2, 0); msghdr2.msg_name = senderAddressStorage; iovecs2[0].iov_base = (IntPtr)ptr_buffer3; if (ret >= 0) { ret = Syscall.recvmsg(so1, msghdr2, 0); } } if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(senderAddress.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual(senderAddress.sin_addr, new InAddr(127, 0, 0, 1)); var senderAddress2 = SockaddrIn.FromSockaddrStorage(senderAddressStorage); Assert.AreEqual(senderAddress2.sa_family, UnixAddressFamily.AF_INET); Assert.AreEqual(senderAddress2.sin_addr, new InAddr(127, 0, 0, 1)); Assert.AreEqual(buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer2[i]); } for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer3[i]); } }); }
/// <summary> /// Creates a socket listening to the supplied endpoint /// </summary> /// <param name="endpoint">The endpoint we listen to.</param> /// <param name="backlog">The connection backlog</param> /// <param name="autodeletedomainsocket">A flag indicating if the domain socket should be attempted deleted</param> public void Bind(EndPoint endpoint, int backlog, bool autodeletedomainsocket) { try { Sockaddr servaddr; var filepath = string.Empty; if (endpoint is IPEndPoint ipe) { // Set up the IP address we are listening on servaddr = new SockaddrIn() { sa_family = UnixAddressFamily.AF_INET, sin_family = UnixAddressFamily.AF_INET, sin_addr = new InAddr() { s_addr = BitConverter.ToUInt32(ipe.Address.GetAddressBytes(), 0) }, sin_port = Syscall.htons((ushort)ipe.Port) }; // Prepare the socket for TCP/IP SetupSocket(UnixAddressFamily.AF_INET); } else if (endpoint is UnixEndPoint upe) { var isHidden = upe.Filename[0] == 0; if (!isHidden) { filepath = upe.Filename; } servaddr = new SockaddrUn(upe.Filename.Substring(isHidden ? 1 : 0), isHidden); // Prepare the socket for Unix Domain Socket SetupSocket(UnixAddressFamily.AF_UNIX); } else if (endpoint is System.Net.Sockets.UnixDomainSocketEndPoint udse) { var name = udse.ToString(); var isHidden = name[0] == 0 || name[0] == '@'; if (!isHidden) { filepath = name; } servaddr = new SockaddrUn(name.Substring(isHidden ? 1 : 0), isHidden); // Prepare the socket for Unix Domain Socket SetupSocket(UnixAddressFamily.AF_UNIX); } else { throw new NotSupportedException($"EndPoint not supported: {endpoint.GetType()}"); } // Bind so we are attached var ret = Syscall.bind(m_socket, servaddr); if (ret < 0) { // Save original error code var err = Stdlib.GetLastError(); // Handle auto-delete of sockets if (autodeletedomainsocket && err == Errno.EADDRINUSE && TryDeleteDomainSocket(servaddr, filepath)) { Syscall.close(m_socket); m_socket = -1; Bind(endpoint, backlog, false); return; } throw new IOException($"Failed to bind to endpoint: {err}"); } ret = Syscall.listen(m_socket, backlog); if (ret < 0) { throw new IOException($"Failed to set socket to listen: {Stdlib.GetLastError()}"); } } catch { // Avoid leaving the listensocket in an invalid state if (m_socket != -1) { try { Syscall.close(m_socket); } catch {} m_socket = -1; } throw; } }
private static extern int ToSockaddrIn (IntPtr source, SockaddrIn destination);
public static bool TryCopy (IntPtr source, SockaddrIn destination) { return ToSockaddrIn (source, destination) == 0; }