public override void Open(string path, bool @abstract) { if (String.IsNullOrEmpty(path)) { throw new ArgumentException("path"); } var addr = new SockaddrUn(path, linuxAbstractNamespace: @abstract); SocketHandle = Syscall.socket(UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0); if (SocketHandle == -1) { UnixMarshal.ThrowExceptionForLastError(); } bool success = false; try { if (Syscall.connect((int)SocketHandle, addr) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Stream = new DBus.Unix.UnixMonoStream((int)SocketHandle); success = true; } finally { if (!success) { int ret = Syscall.close((int)SocketHandle); SocketHandle = -1; if (ret == -1) { UnixMarshal.ThrowExceptionForLastError(); } } } }
[ExpectedException(typeof(ArgumentOutOfRangeException))] // SOCK_NONBLOCK, SOCK_CLOEXEC not supported #endif public void Accept4() { WithSockets(UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => { var address = new SockaddrUn(TempFolder + "/socket2"); if (Syscall.bind(so1, address) < 0) { UnixMarshal.ThrowExceptionForLastError(); } if (Syscall.listen(so1, 5) < 0) { UnixMarshal.ThrowExceptionForLastError(); } if (Syscall.connect(so2, address) < 0) { UnixMarshal.ThrowExceptionForLastError(); } int so3; var remote = new SockaddrUn(); if ((so3 = Syscall.accept4(so1, remote, UnixSocketFlags.SOCK_CLOEXEC | UnixSocketFlags.SOCK_NONBLOCK)) < 0) { UnixMarshal.ThrowExceptionForLastError(); } try { int _flags; if ((_flags = Syscall.fcntl(so3, FcntlCommand.F_GETFL)) < 0) { UnixMarshal.ThrowExceptionForLastError(); } var flags = NativeConvert.ToOpenFlags(_flags); Assert.IsTrue((flags & OpenFlags.O_NONBLOCK) != 0); int _flagsFD; if ((_flagsFD = Syscall.fcntl(so3, FcntlCommand.F_GETFD)) < 0) { UnixMarshal.ThrowExceptionForLastError(); } // FD_CLOEXEC must be set //var flagsFD = NativeConvert.ToFdFlags (_flagsFD); //Assert.IsTrue ((flagsFD & FdFlags.FD_CLOEXEC) != 0); Assert.IsTrue(_flagsFD != 0); } finally { if (Syscall.close(so3) < 0) { UnixMarshal.ThrowExceptionForLastError(); } } }); }
public void SockaddrUnTest() { var address1 = new SockaddrUn("/tmp/foo"); Assert.AreEqual(address1.Path, "/tmp/foo"); Assert.IsFalse(address1.IsLinuxAbstractNamespace); var storage = address1.ToSockaddrStorage(); var address2 = SockaddrUn.FromSockaddrStorage(storage); Assert.AreEqual(address1, address2); var sockaddr = Sockaddr.FromSockaddrStorage(storage); Assert.AreEqual(sockaddr.sa_family, address1.sa_family); var address3 = new SockaddrUn("/tmp/bar", linuxAbstractNamespace: true); Assert.AreEqual(address3.Path, "/tmp/bar"); Assert.IsTrue(address3.IsLinuxAbstractNamespace); var address4 = new SockaddrUn(new string ('X', 9000)); Assert.AreEqual(address4.Path, new string ('X', 9000)); Assert.IsFalse(address4.IsLinuxAbstractNamespace); var storage2 = address4.ToSockaddrStorage(); var address5 = SockaddrUn.FromSockaddrStorage(storage2); Assert.AreEqual(address4, address5); // Test the malloc() path for long SockaddrUn adresses (the syscalls will fail because the fd is invalid and because the path is too long) Syscall.bind(-1, address4); Syscall.getsockname(-1, address4); Assert.AreEqual("{sa_family=AF_UNIX, sun_path=\"/tmp/foo\"}", address1.ToString()); Assert.AreEqual("{sa_family=AF_UNIX, sun_path=\"\\0/tmp/bar\"}", address3.ToString()); }
public void Accept4 () { WithSockets (UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => { var address = new SockaddrUn (TempFolder + "/socket2"); if (Syscall.bind (so1, address) < 0) UnixMarshal.ThrowExceptionForLastError (); if (Syscall.listen (so1, 5) < 0) UnixMarshal.ThrowExceptionForLastError (); if (Syscall.connect (so2, address) < 0) UnixMarshal.ThrowExceptionForLastError (); int so3; var remote = new SockaddrUn (); if ((so3 = Syscall.accept4 (so1, remote, UnixSocketFlags.SOCK_CLOEXEC | UnixSocketFlags.SOCK_NONBLOCK)) < 0) UnixMarshal.ThrowExceptionForLastError (); try { int _flags; if ((_flags = Syscall.fcntl (so3, FcntlCommand.F_GETFL)) < 0) UnixMarshal.ThrowExceptionForLastError (); var flags = NativeConvert.ToOpenFlags (_flags); Assert.IsTrue ((flags & OpenFlags.O_NONBLOCK) != 0); int _flagsFD; if ((_flagsFD = Syscall.fcntl (so3, FcntlCommand.F_GETFD)) < 0) UnixMarshal.ThrowExceptionForLastError (); // FD_CLOEXEC must be set //var flagsFD = NativeConvert.ToFdFlags (_flagsFD); //Assert.IsTrue ((flagsFD & FdFlags.FD_CLOEXEC) != 0); Assert.IsTrue (_flagsFD != 0); } finally { if (Syscall.close (so3) < 0) UnixMarshal.ThrowExceptionForLastError (); } }); }
public void UnixAccept () { var address = new SockaddrUn (TempFolder + "/socket1"); var address2 = SockaddrUn.FromSockaddrStorage (address.ToSockaddrStorage ()); Assert.AreEqual (address, address2); WithSockets (UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => { if (Syscall.bind (so1, address) < 0) UnixMarshal.ThrowExceptionForLastError (); if (Syscall.listen (so1, 5) < 0) UnixMarshal.ThrowExceptionForLastError (); if (Syscall.connect (so2, address) < 0) UnixMarshal.ThrowExceptionForLastError (); var address3 = new SockaddrUn (); if (Syscall.getsockname (so1, address3) < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (address, address3); var address4 = new SockaddrStorage (); if (Syscall.getsockname (so1, address4) < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (UnixAddressFamily.AF_UNIX, address4.sa_family); Assert.AreEqual (address3, SockaddrUn.FromSockaddrStorage (address4)); var address5 = new SockaddrUn (); if (Syscall.getsockname (so1, address5) < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (UnixAddressFamily.AF_UNIX, address5.sa_family); // Check getsockname(socket, null) if (Syscall.getsockname (so1, null) < 0) UnixMarshal.ThrowExceptionForLastError (); int so3; var remote = new SockaddrUn (); if ((so3 = Syscall.accept (so1, remote)) < 0) UnixMarshal.ThrowExceptionForLastError (); try { // Send and receive a few bytes long ret; var buffer1 = new byte[] { 42, 43, 44 }; ret = Syscall.send (so2, buffer1, (ulong) buffer1.Length, 0); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); var buffer2 = new byte[1024]; ret = Syscall.recv (so3, buffer2, (ulong) buffer2.Length, 0); if (ret < 0) UnixMarshal.ThrowExceptionForLastError (); Assert.AreEqual (buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) Assert.AreEqual (buffer1[i], buffer2[i]); } finally { if (Syscall.close (so3) < 0) UnixMarshal.ThrowExceptionForLastError (); } }); }
public void SockaddrUnTest () { var address1 = new SockaddrUn ("/tmp/foo"); Assert.AreEqual (address1.Path, "/tmp/foo"); Assert.IsFalse (address1.IsLinuxAbstractNamespace); var storage = address1.ToSockaddrStorage (); var address2 = SockaddrUn.FromSockaddrStorage (storage); Assert.AreEqual (address1, address2); var sockaddr = Sockaddr.FromSockaddrStorage (storage); Assert.AreEqual (sockaddr.sa_family, address1.sa_family); var address3 = new SockaddrUn ("/tmp/bar", linuxAbstractNamespace:true); Assert.AreEqual (address3.Path, "/tmp/bar"); Assert.IsTrue (address3.IsLinuxAbstractNamespace); var address4 = new SockaddrUn (new string ('X', 9000)); Assert.AreEqual (address4.Path, new string ('X', 9000)); Assert.IsFalse (address4.IsLinuxAbstractNamespace); var storage2 = address4.ToSockaddrStorage (); var address5 = SockaddrUn.FromSockaddrStorage (storage2); Assert.AreEqual (address4, address5); // Test the malloc() path for long SockaddrUn adresses (the syscalls will fail because the fd is invalid and because the path is too long) Syscall.bind (-1, address4); Syscall.getsockname (-1, address4); Assert.AreEqual ("{sa_family=AF_UNIX, sun_path=\"/tmp/foo\"}", address1.ToString ()); Assert.AreEqual ("{sa_family=AF_UNIX, sun_path=\"\\0/tmp/bar\"}", address3.ToString ()); }
public void UnixAccept() { var address = new SockaddrUn(TempFolder + "/socket1"); var address2 = SockaddrUn.FromSockaddrStorage(address.ToSockaddrStorage()); Assert.AreEqual(address, address2); WithSockets(UnixAddressFamily.AF_UNIX, UnixSocketType.SOCK_STREAM, 0, (so1, so2) => { if (Syscall.bind(so1, address) < 0) { UnixMarshal.ThrowExceptionForLastError(); } if (Syscall.listen(so1, 5) < 0) { UnixMarshal.ThrowExceptionForLastError(); } if (Syscall.connect(so2, address) < 0) { UnixMarshal.ThrowExceptionForLastError(); } var address3 = new SockaddrUn(); if (Syscall.getsockname(so1, address3) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(address, address3); var address4 = new SockaddrStorage(); if (Syscall.getsockname(so1, address4) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(UnixAddressFamily.AF_UNIX, address4.sa_family); Assert.AreEqual(address3, SockaddrUn.FromSockaddrStorage(address4)); var address5 = new SockaddrUn(); if (Syscall.getsockname(so1, address5) < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(UnixAddressFamily.AF_UNIX, address5.sa_family); // Check getsockname(socket, null) if (Syscall.getsockname(so1, null) < 0) { UnixMarshal.ThrowExceptionForLastError(); } int so3; var remote = new SockaddrUn(); if ((so3 = Syscall.accept(so1, remote)) < 0) { UnixMarshal.ThrowExceptionForLastError(); } try { // Send and receive a few bytes long ret; var buffer1 = new byte[] { 42, 43, 44 }; ret = Syscall.send(so2, buffer1, (ulong)buffer1.Length, 0); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } var buffer2 = new byte[1024]; ret = Syscall.recv(so3, buffer2, (ulong)buffer2.Length, 0); if (ret < 0) { UnixMarshal.ThrowExceptionForLastError(); } Assert.AreEqual(buffer1.Length, ret); for (int i = 0; i < buffer1.Length; i++) { Assert.AreEqual(buffer1[i], buffer2[i]); } } finally { if (Syscall.close(so3) < 0) { UnixMarshal.ThrowExceptionForLastError(); } } }); }
/// <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; } }