Exemplo n.º 1
0
        /// <summary>
        /// Closes the socket if it is open or listening.
        /// </summary>
        public void Close()
        {
            if (closing || Parent.State == State.Closed)
            {
                return;
            }
            closing = true;

            try
            {
                var oldState = Parent.State;
                if (oldState == State.Connected || oldState == State.Listening)
                {
                    Parent.ChangeState(State.Closing);
                    if (socketStream != null)
                    {
                        socketStream.Dispose(); // Should take care of MOST instances, this Dispose also closes the socket.
                    }
                    else if (socket != null && oldState == State.Listening)
                    {
                        socket.Close(); // Listeners don't create a stream, so this handles those
                    }
                    else if (socket != null && socket.IsConnected)
                    {
                        // Edge cases and errors could potentially leave us with a connected socket but without a stream.
                        socket.Shutdown(SocketShutdown.Both);
                        socket.Close();
                    }
                    socketStream = null;
                    socket       = null;
                }
                Parent.ChangeState(State.Closed);
                if (oldState == State.Connected)
                {
                    Parent.OnDisconnected();
                }
            }
            catch (Exception ex)
            {
                Parent.OnErrorReceived(Parent, ex.AsEventArgs());
            }
            finally
            {
                closing = false;
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Places the <see cref="WinSocket"/> into a listening state.
        /// </summary>
        /// <param name="ipAddress">An <see cref="IPAddress"/> containing the IP address to start listening on.  Null to listen on all available interfaces.</param>
        /// <param name="port">The port to start listening on.</param>
        /// <remarks>Threading hasn't really started yet, so allow exceptions to bubble-up.</remarks>
        public void Listen(IPAddress ipAddress, int port)
        {
            bool ipWasNull = (ipAddress == null);

            if (ipWasNull)
            {
                ipAddress = Socket.OSSupportsIPv6 ? IPAddress.IPv6Any : IPAddress.Any;
            }

            AddressFamily family = ipAddress.AddressFamily;
            SocketType    stype  = (Parent.Protocol == Protocol.Tcp) ? SocketType.Stream : SocketType.Dgram;
            ProtocolType  ptype  = (Parent.Protocol == Protocol.Tcp) ? ProtocolType.Tcp : ProtocolType.Udp;

            int portUsed = port;

            socket = new AsyncSocket(family, stype, ptype);
            if (ipWasNull && ipAddress == IPAddress.IPv6Any)
            {
                socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
            }
            if (ptype == ProtocolType.Udp)
            {
                socket.SetSocketOption((family == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP), SocketOptionName.PacketInformation, true);
            }

            var localEndpoint = new IPEndPoint(ipAddress, port);

            socket.Bind(localEndpoint);
            if (port == 0)
            {
                portUsed = ((IPEndPoint)socket.LocalEndPoint).Port;
                Parent.ChangeLocalPort(portUsed);
            }

            if (Parent.Protocol == Protocol.Tcp)
            {
                (new Thread(ListenTCP)).Start();
            }
            else // UPD
            {
                (new Thread(ListenUDP)).Start();
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Establishes a connection to a remote host.
        /// </summary>
        /// <param name="remoteHostOrIp">A value containing the Hostname or IP address of the remote host.</param>
        /// <param name="remotePort">A value indicating the port on the remote host to connect to.</param>
        /// <param name="sslHost">The name of the host to validate the certificate for.</param>
        /// <param name="localIp">A value indicating the IP address the client should connect from.</param>
        /// <param name="localPort">A value indicating the port the client should connect from.</param>
        public async void Connect(string remoteHostOrIp, int remotePort, string sslHost, string localIp, int localPort)
        {
            if (Parent.State != State.Closed)
            {
                throw new WinsockException("Cannot connect to a remote host when not Closed.");
            }

            /**
             * First we need to make sure we have an IP address.
             * If not - we need to try and resolve the fully qualified domain.
             */
            Parent.ChangeState(State.ResolvingHost);
            IPAddress resolvedRemoteIP = null, resolvedLocalIP = null;

            if (!IPAddress.TryParse(remoteHostOrIp, out resolvedRemoteIP))
            {
                IPHostEntry entry = await Dns.GetHostEntryAsync(remoteHostOrIp);

                if (entry == null || entry.AddressList.Length == 0)
                {
                    string name = (entry != null) ? entry.HostName : remoteHostOrIp;
                    throw new WinsockException(string.Format("Hostname \"{0}\" could not be resolved.", name));
                }
                resolvedRemoteIP = entry.AddressList[0];
            }

            if (!string.IsNullOrWhiteSpace(localIp) && !IPAddress.TryParse(localIp, out resolvedLocalIP))
            {
                throw new WinsockException(string.Format("The value \"{0}\" is not a valid IP address for local binding.", localIp));
            }
            Parent.ChangeState(State.HostResolved);

            /**
             * Take our IP address and attempt to create the connection.
             * Upon successfull connections - different BeginReceives could be called
             * depending on if this was an attempt at a SECURE connection.
             */
            IPEndPoint endPoint      = new IPEndPoint(resolvedRemoteIP, remotePort);
            IPEndPoint localEndPoint = (resolvedLocalIP != null) ? new IPEndPoint(resolvedLocalIP, localPort) : null;

            socket = new AsyncSocket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            Parent.ChangeState(State.Connecting);

            bool connectFail = false;

            try
            {
                if (localEndPoint != null)
                {
                    socket.Bind(localEndPoint);
                }
                await socket.ConnectAsync(endPoint);
            }
            catch (Exception ex)
            {
                connectFail = true;
                Parent.ChangeState(State.Closed);
                Parent.OnErrorReceived(Parent, ErrorReceivedEventArgs.Create(ex));
            }

            if (!connectFail)
            {
                Parent.ChangeState(State.Connected);
                Parent.OnConnected(endPoint);
                if (sslHost != null)
                {
                    BeginReceive(false, sslHost);
                }
                else
                {
                    BeginReceive(false);
                }
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Closes the socket if it is open or listening.
        /// </summary>
        public void Close()
        {
            if (closing || Parent.State == State.Closed) return;
            closing = true;

            try
            {
                var oldState = Parent.State;
                if (oldState == State.Connected || oldState == State.Listening)
                {
                    Parent.ChangeState(State.Closing);
                    if (socketStream != null)
                        socketStream.Dispose(); // Should take care of MOST instances, this Dispose also closes the socket.
                    else if (socket != null && oldState == State.Listening)
                        socket.Close(); // Listeners don't create a stream, so this handles those
                    else if (socket != null && socket.IsConnected)
                    {
                        // Edge cases and errors could potentially leave us with a connected socket but without a stream.
                        socket.Shutdown(SocketShutdown.Both);
                        socket.Close();
                    }
                    socketStream = null;
                    socket = null;
                }
                Parent.ChangeState(State.Closed);
            }
            catch (Exception ex)
            {
                Parent.OnErrorReceived(Parent, ex.AsEventArgs());
            }
            finally
            {
                closing = false;
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Places the <see cref="WinSocket"/> into a listening state.
        /// </summary>
        /// <param name="ipAddress">An <see cref="IPAddress"/> containing the IP address to start listening on.  Null to listen on all available interfaces.</param>
        /// <param name="port">The port to start listening on.</param>
        /// <remarks>Threading hasn't really started yet, so allow exceptions to bubble-up.</remarks>
        public void Listen(IPAddress ipAddress, int port)
        {
            bool ipWasNull = (ipAddress == null);
            if (ipWasNull)
                ipAddress = Socket.OSSupportsIPv6 ? IPAddress.IPv6Any : IPAddress.Any;

            AddressFamily family = ipAddress.AddressFamily;
            SocketType stype = (Parent.Protocol == Protocol.Tcp) ? SocketType.Stream : SocketType.Dgram;
            ProtocolType ptype = (Parent.Protocol == Protocol.Tcp) ? ProtocolType.Tcp : ProtocolType.Udp;

            int portUsed = port;
            socket = new AsyncSocket(family, stype, ptype);
            if (ipWasNull && ipAddress == IPAddress.IPv6Any)
                socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, 0);
            if (ptype == ProtocolType.Udp)
                socket.SetSocketOption((family == AddressFamily.InterNetworkV6 ? SocketOptionLevel.IPv6 : SocketOptionLevel.IP), SocketOptionName.PacketInformation, true);

            var localEndpoint = new IPEndPoint(ipAddress, port);
            socket.Bind(localEndpoint);
            if (port == 0)
            {
                portUsed = ((IPEndPoint)socket.LocalEndPoint).Port;
                Parent.ChangeLocalPort(portUsed);
            }

            if (Parent.Protocol == Protocol.Tcp)
                (new Thread(ListenTCP)).Start();
            else // UPD
                (new Thread(ListenUDP)).Start();
        }
Exemplo n.º 6
0
        /// <summary>
        /// Accepts an incoming connection and starts the data listener.
        /// </summary>
        /// <param name="client">The client to accept.</param>
        /// <returns>true on success; otherwise false.</returns>
        public bool Accept(Socket client)
        {
            if (Parent.State != State.Closed)
                throw new WinsockException("Cannot accept a connection while the State is not closed.");

            try
            {
                socket = new AsyncSocket(client);
                Parent.ChangeState(State.Connected);
                BeginReceive(true);
                return true;
            }
            catch (Exception ex)
            {
                Parent.OnErrorReceived(Parent, ex.AsEventArgs());
                return false;
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Establishes a connection to a remote host.
        /// </summary>
        /// <param name="remoteHostOrIp">A value containing the Hostname or IP address of the remote host.</param>
        /// <param name="remotePort">A value indicating the port on the remote host to connect to.</param>
        /// <param name="sslHost">The name of the host to validate the certificate for.</param>
        public async void Connect(string remoteHostOrIp, int remotePort, string sslHost)
        {
            if (Parent.State != State.Closed)
                throw new WinsockException("Cannot connect to a remote host when not Closed.");

            /**
             * First we need to make sure we have an IP address.
             * If not - we need to try and resolve the fully qualified domain.
             */
            Parent.ChangeState(State.ResolvingHost);
            IPAddress resolvedIP = null;
            if (!IPAddress.TryParse(remoteHostOrIp, out resolvedIP))
            {
                IPHostEntry entry = await Dns.GetHostEntryAsync(remoteHostOrIp);
                if (entry == null || entry.AddressList.Length == 0)
                {
                    string name = (entry != null) ? entry.HostName : remoteHostOrIp;
                    throw new WinsockException(string.Format("Hostname \"{0}\" could not be resolved.", name));
                }
                resolvedIP = entry.AddressList[0];
            }
            Parent.ChangeState(State.HostResolved);

            /**
             * Take our IP address and attempt to create the connection.
             * Upon successfull connections - different BeginReceives could be called
             * depending on if this was an attempt at a SECURE connection.
             */
            IPEndPoint endPoint = new IPEndPoint(resolvedIP, remotePort);
            socket = new AsyncSocket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            Parent.ChangeState(State.Connecting);

            await socket.ConnectAsync(endPoint);
            Parent.ChangeState(State.Connected);
            if (sslHost != null) BeginReceive(false, sslHost);
            else BeginReceive(false);
        }