예제 #1
0
        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();
                    }
                }
            }
        }
예제 #2
0
        [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();
                    }
                }
            });
        }
예제 #3
0
        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());
        }
예제 #4
0
파일: SocketTest.cs 프로젝트: ZZHGit/mono
		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 ();
				}
			});
		}
예제 #5
0
파일: SocketTest.cs 프로젝트: ZZHGit/mono
		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 ();
				}
			});
		}
예제 #6
0
파일: SocketTest.cs 프로젝트: ZZHGit/mono
		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 ());
		}
예제 #7
0
        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();
                    }
                }
            });
        }
예제 #8
0
        /// <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;
            }
        }