Example #1
0
        private NSOutputStream GetStreamForConnectionConext(SocketEventArgs args)
        {
            NSOutputStream stream;

            lock (_connectedClients)
            {
                if (!_connectedClients.ContainsKey(args.ClientUid))
                {
                    args.SocketException = new InvalidOperationException("No remote connection has been established.");
                    args.Complete();
                    return(null);
                }

                ConnectedClientInfo info = _connectedClients[args.ClientUid];

                try
                {
                    stream = info.Stream.Output;
                }
                catch (Exception ex)
                {
                    args.SocketException = ex;
                    args.Complete();
                    return(null);
                }
            }
            return(stream);
        }
Example #2
0
        public void WriteAsync(SocketEventArgs args)
        {
            NSOutputStream stream = GetStreamForConnectionConext(args);

            if (stream == null)
            {
                // OnCompleted called in GetStreamForConnectionConext(), just return here.
                return;
            }

            try
            {
                EventHandler <NSStreamEventArgs> handler = null;
                handler = (_, e1) =>
                {
                    stream.OnEvent -= handler;

                    if (e1.StreamEvent == NSStreamEvent.ErrorOccurred)
                    {
                        args.SocketException = new Exception("Something unexpected happened. " + e1.StreamEvent.ToString());
                        args.Complete();
                    }

                    if (e1.StreamEvent != NSStreamEvent.HasSpaceAvailable)
                    {
                        return;
                    }

                    WriteAsyncInternal(stream, args);
                };

                if (stream.HasSpaceAvailable())
                {
                    WriteAsyncInternal(stream, args);
                }
                else
                {
                    stream.OnEvent += handler;
                }
            }
            catch (ObjectDisposedException)
            {
                // Effectively ignoring this
                args.Complete();
            }
            catch (Exception ex)
            {
                args.SocketException =
                    new Exception("Unable to write to the TCP connection. See inner exception for details.", ex);
                args.Complete();
            }
        }
Example #3
0
        private void WriteAsyncInternal(NSOutputStream stream, SocketEventArgs args)
        {
            byte[] sendBuffer = args.MessageToSend.Serialize();

            EventHandler <NSStreamEventArgs> completedHandler = null;

            completedHandler = (sender, e) =>
            {
                stream.OnEvent -= completedHandler;

                if (args.MessageToSend is IMqttIdMessage)
                {
                    var msgWithId = args.MessageToSend as IMqttIdMessage;
                    _logger.LogMessage("Socket", LogLevel.Verbose,
                                       string.Format("Sent message type '{0}', ID={1}.", msgWithId.MessageType,
                                                     msgWithId.MessageId));
                }
                else
                {
                    _logger.LogMessage("Socket", LogLevel.Verbose,
                                       string.Format("Sent message type '{0}'.", args.MessageToSend.MessageType));
                }

                if (e.StreamEvent == NSStreamEvent.ErrorOccurred)
                {
                    args.SocketException = new Exception("Socket error occured: " + e.StreamEvent.ToString());
                }

                args.Complete();
            };

            stream.OnEvent += completedHandler;
            stream.Write(sendBuffer, (nuint)sendBuffer.Length);
        }
Example #4
0
        public async void ConnectAsync(string ipOrHost, int port, SocketEventArgs args)
        {
            _socket = new StreamSocket();
            var server = new HostName(ipOrHost);

            // TCP timeouts in WinRT are excessive, shorten them here using task cancellation
            var cts = new CancellationTokenSource();

            try
            {
                cts.CancelAfter(MqttProtocolInformation.Settings.NetworkTimeout * 1000);
                _logger.LogMessage("Socket", LogLevel.Verbose, string.Format("Authenticating client certificate with remote host CN={0}", server.CanonicalName));
                await _socket.ConnectAsync(server, port.ToString(), GetSocketProtectionLevel(args.EncryptionLevel)).AsTask(cts.Token);

                _clientUid = args.ClientUid;
                StartReceiving();
            }
            catch (TaskCanceledException)
            {
                args.SocketException = new IOException("Timeout error while trying to connect.");
                _clientUid           = null;
                _socket.Dispose();
                _socket = null;
            }
            catch (Exception ex)
            {
                args.SocketException = ex;
                _clientUid           = null;
                _socket.Dispose();
                _socket = null;
            }
            args.Complete();
        }
        public async void ConnectAsync(string ipOrHost, int port, SocketEventArgs args)
        {
            _socket = new StreamSocket();
            var server = new HostName(ipOrHost);

            // TCP timeouts in WinRT are excessive, shorten them here using task cancellation
            var cts = new CancellationTokenSource();

            try
            {
                cts.CancelAfter(MqttProtocolInformation.Settings.NetworkTimeout * 1000);
                _logger.LogMessage("Socket", LogLevel.Verbose, string.Format("Authenticating client certificate with remote host CN={0}", server.CanonicalName));
                await _socket.ConnectAsync(server, port.ToString(), GetSocketProtectionLevel(args.EncryptionLevel)).AsTask(cts.Token);
                _clientUid = args.ClientUid;
                StartReceiving();
            }
            catch (TaskCanceledException)
            {
                args.SocketException = new IOException("Timeout error while trying to connect.");
                _clientUid = null;
                _socket.Dispose();
                _socket = null;
            }
            catch (Exception ex)
            {
                args.SocketException = ex;
                _clientUid = null;
                _socket.Dispose();
                _socket = null;
            }
            args.Complete();
        }
Example #6
0
        public void ConnectAsync(string ipOrHost, int port, SocketEventArgs args)
        {
            var t = new Thread(() =>
            {
                IPEndPoint ep;
                try
                {
                    ep = ResolveIpAddress(ipOrHost, port);
                }
                catch (Exception ex)
                {
                    args.SocketException     = ex;
                    args.AdditionalErrorInfo = "Unable to resolve ip address or host name.";
                    args.Complete();
                    return;
                }

                _encryptionLevel = GetSslProtocol(args.EncryptionLevel);
                _clientUid       = args.ClientUid;

                try
                {
                    CreateSocketAndConnect(ep);
                    StartReceiving();
                }
                catch (Exception ex)
                {
                    _clientUid           = null;
                    args.SocketException = ex;
                }
                finally
                {
                    args.Complete();
                }
            });

            // Start the writer thread
            _writerThread = new Thread(WriteMessageWorker);
            _writerThread.Start();

            // Go connect
            t.Start();
        }
Example #7
0
        public void WriteAsync(SocketEventArgs args)
        {
            if (_socket == null)
            {
                args.SocketException = new InvalidOperationException("No server connection has been established.");
                args.Complete();
                return;
            }

            try
            {
                // Write data to the socket
                var writer = new DataWriter(_socket.OutputStream);
                writer.WriteBytes(args.MessageToSend.Serialize());
                writer.StoreAsync().Completed += (info, status) =>
                {
                    writer.DetachStream();
                    writer.Dispose();

                    if (args.MessageToSend is IMqttIdMessage)
                    {
                        var msgWithId = args.MessageToSend as IMqttIdMessage;
                        _logger.LogMessage("Socket", LogLevel.Verbose, string.Format("Sent message type '{0}', ID={1} to server.", msgWithId.MessageType, msgWithId.MessageId));
                    }
                    else
                    {
                        _logger.LogMessage("Socket", LogLevel.Verbose, string.Format("Sent message type '{0}' to server.", args.MessageToSend.MessageType));
                    }

                    if (info.Status == AsyncStatus.Error)
                    {
                        args.SocketException = info.ErrorCode;
                    }
                    args.Complete();
                };
            }
            catch (Exception ex)
            {
                args.SocketException = ex;
                args.Complete();
            }
        }
        public async void ConnectAsync(string ipOrHost, int port, SocketEventArgs args)
        {
            TcpClient tcpClient;
            IPAddress ip;
            Task connectTask;

            if (IPAddress.TryParse(ipOrHost, out ip))
            {
                _remoteHost = "";
                var endPoint = new IPEndPoint(ip, port);
                tcpClient = CreateSocket(endPoint.AddressFamily);
                connectTask = tcpClient.ConnectAsync(endPoint.Address, port);
            }
            else
            {
                _remoteHost = ipOrHost;
                tcpClient = CreateSocket(AddressFamily.Unspecified);
                connectTask = tcpClient.ConnectAsync(ipOrHost, port);
            }

            await connectTask.ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    if (task.Exception != null && task.Exception.InnerExceptions.Count > 0)
                    {
                        args.SocketException = task.Exception.InnerExceptions[0];
                    }
                    else
                    {
                        args.SocketException = new Exception("Unknown socket error.");
                    }
                }
                else
                {
                    _socketWorker.ConnectTcpClient(tcpClient, port, args.EncryptionLevel, args.ClientUid);
                }
                args.Complete();
            });
        }
Example #9
0
        public async void ConnectAsync(string ipOrHost, int port, SocketEventArgs args)
        {
            TcpClient tcpClient;
            IPAddress ip;
            Task      connectTask;

            if (IPAddress.TryParse(ipOrHost, out ip))
            {
                _remoteHost = "";
                var endPoint = new IPEndPoint(ip, port);
                tcpClient   = CreateSocket(endPoint.AddressFamily);
                connectTask = tcpClient.ConnectAsync(endPoint.Address, port);
            }
            else
            {
                _remoteHost = ipOrHost;
                tcpClient   = CreateSocket(AddressFamily.Unspecified);
                connectTask = tcpClient.ConnectAsync(ipOrHost, port);
            }

            await connectTask.ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    if (task.Exception != null && task.Exception.InnerExceptions.Count > 0)
                    {
                        args.SocketException = task.Exception.InnerExceptions[0];
                    }
                    else
                    {
                        args.SocketException = new Exception("Unknown socket error.");
                    }
                }
                else
                {
                    _socketWorker.ConnectTcpClient(tcpClient, port, args.EncryptionLevel, args.ClientUid);
                }
                args.Complete();
            });
        }
Example #10
0
        public void WriteAsync(SocketEventArgs args)
        {
            SentMessages.Add(args.MessageToSend.MessageType);
            args.Complete();

            // Mock a server that does not send appropriate response
            if (DoNotRespond)
            {
                return;
            }

            // This section mocks the expected response behavior from an MQTT broker
            switch (args.MessageToSend.MessageType)
            {
                case MessageType.Connect:
                    var conAck = new MqttConnectAckMessageBuilder();
                    MessageReceived(new MqttNetEventArgs
                    {
                        Message = conAck.GetMessage(),
                        ClientUid = args.ClientUid
                    });
                    break;

                case MessageType.Subscribe:
                    var subMsg = args.MessageToSend as IMqttIdMessage;
                    var subAck = new MqttSubscribeAckMessageBuilder
                    {
                        MessageId = subMsg.MessageId
                   };
                    MessageReceived(new MqttNetEventArgs
                    {
                        Message = subAck.GetMessage(),
                        ClientUid = args.ClientUid
                    });
                    break;

                case MessageType.Unsubscribe:
                    var unsubMsg = args.MessageToSend as IMqttIdMessage;
                    var unsubAck = new MqttUnsubscribeAckMessageBuilder
                    {
                        MessageId = unsubMsg.MessageId
                    };
                    MessageReceived(new MqttNetEventArgs
                    {
                        Message = unsubAck.GetMessage(),
                        ClientUid = args.ClientUid
                    });
                    break;

                case MessageType.PingReq:
                    var pingResp = new MqttPingResponseMessageBuilder();
                    MessageReceived(new MqttNetEventArgs
                    {
                        Message = pingResp.GetMessage(),
                        ClientUid = args.ClientUid
                    });
                    break;

                case MessageType.Publish:
                    var publishMsg = args.MessageToSend as IMqttIdMessage;
                    // Mock publish response behavior
                    if (args.MessageToSend.QualityOfService == QualityOfService.AtLeastOnce)
                    {
                        var msgRcv = new MqttPublishAckMessageBuilder
                        {
                            MessageId = publishMsg.MessageId
                        };
                        MessageReceived(new MqttNetEventArgs
                        {
                            Message = msgRcv.GetMessage(),
                            ClientUid = args.ClientUid
                        });
                    }
                    else if (args.MessageToSend.QualityOfService == QualityOfService.ExactlyOnce)
                    {
                        var msgRcv = new MqttPublishReceivedMessageBuilder()
                        {
                            MessageId = publishMsg.MessageId
                        };
                        MessageReceived(new MqttNetEventArgs
                        {
                            Message = msgRcv.GetMessage(),
                            ClientUid = args.ClientUid
                        });
                    }
                    break;

                case MessageType.PubRec:
                    var pubRec = args.MessageToSend as IMqttIdMessage;
                    var pubRel1 = new MqttPublishReleaseMessageBuilder
                    {
                        MessageId = pubRec.MessageId
                    };
                    MessageReceived(new MqttNetEventArgs
                    {
                        Message = pubRel1.GetMessage(),
                        ClientUid = args.ClientUid
                    });
                    break;

                case MessageType.PubRel:
                    var pubRel2 = args.MessageToSend as IMqttIdMessage;
                    var pubComp = new MqttPublishCompleteMessageBuilder
                    {
                        MessageId = pubRel2.MessageId
                    };
                    MessageReceived(new MqttNetEventArgs
                    {
                        Message = pubComp.GetMessage(),
                        ClientUid = args.ClientUid
                    });
                    break;
            }
        }
Example #11
0
 public void ConnectAsync(string ipAddress, int port, SocketEventArgs args)
 {
     _isConnected = true;
     args.Complete();
 }
Example #12
0
        public async void WriteAsync(SocketEventArgs args)
        {
            Stream stream = GetStreamForConnectionConext(args);

            if (stream == null)
            {
                // OnCompleted called in GetStreamForConnectionConext(), just return here.
                return;
            }

            // Here we are outside the lock, stream can be closed beneath us
            // Typical scenario is the client asynchronously disconnects before we're finished sending it a message.
            // For now, I'm OK with this. It's better than balling this up with locks.
            try
            {
                if (stream.CanWrite)
                {
                    byte[] sendBuffer = args.MessageToSend.Serialize();
                    await stream.WriteAsync(sendBuffer, 0, sendBuffer.Length).ContinueWith(task =>
                    {
                        stream.Flush();
                        if (args.MessageToSend is IMqttIdMessage)
                        {
                            var msgWithId = args.MessageToSend as IMqttIdMessage;
                            _logger.LogMessage("Socket", LogLevel.Verbose,
                                               string.Format("Sent message type '{0}', ID={1}.", msgWithId.MessageType,
                                                             msgWithId.MessageId));
                        }
                        else
                        {
                            _logger.LogMessage("Socket", LogLevel.Verbose,
                                               string.Format("Sent message type '{0}'.", args.MessageToSend.MessageType));
                        }
                        if (task.IsFaulted)
                        {
                            if (task.Exception != null && task.Exception.InnerExceptions.Count > 0)
                            {
                                args.SocketException = task.Exception.InnerExceptions[0];
                            }
                            else
                            {
                                args.SocketException = new Exception("Unknown socket error.");
                            }
                        }
                        args.Complete();
                    });
                }
                else
                {
                    args.SocketException = new Exception("Connection state is invalid. Please try reconnecting.");
                    args.Complete();
                }
            }
            catch (ObjectDisposedException)
            {
                // Effectively ignoring this
                args.Complete();
            }
            catch (Exception ex)
            {
                args.SocketException =
                    new Exception("Unable to write to the TCP connection. See inner exception for details.", ex);
                args.Complete();
            }
        }
        private Stream GetStreamForConnectionConext(SocketEventArgs args)
        {
            Stream stream;
            lock (_connectedClients)
            {
                if (!_connectedClients.ContainsKey(args.ClientUid))
                {
                    args.SocketException = new InvalidOperationException("No remote connection has been established.");
                    args.Complete();
                    return null;
                }

                ConnectedClientInfo info = _connectedClients[args.ClientUid];

                try
                {
                    stream = GetStreamForConnection(info);
                }
                catch (Exception ex)
                {
                    args.SocketException = ex;
                    args.Complete();
                    return null;
                }
            }
            return stream;
        }
        public async void WriteAsync(SocketEventArgs args)
        {
            Stream stream = GetStreamForConnectionConext(args);

            if (stream == null)
            {
                // OnCompleted called in GetStreamForConnectionConext(), just return here.
                return;
            }

            // Here we are outside the lock, stream can be closed beneath us
            // Typical scenario is the client asynchronously disconnects before we're finished sending it a message.
            // For now, I'm OK with this. It's better than balling this up with locks.
            try
            {
                if (stream.CanWrite)
                {
                    byte[] sendBuffer = args.MessageToSend.Serialize();
                    await stream.WriteAsync(sendBuffer, 0, sendBuffer.Length).ContinueWith(task =>
                    {
                        stream.Flush();
                        if (args.MessageToSend is IMqttIdMessage)
                        {
                            var msgWithId = args.MessageToSend as IMqttIdMessage;
                            _logger.LogMessage("Socket", LogLevel.Verbose,
                                string.Format("Sent message type '{0}', ID={1}.", msgWithId.MessageType,
                                    msgWithId.MessageId));
                        }
                        else
                        {
                            _logger.LogMessage("Socket", LogLevel.Verbose,
                                string.Format("Sent message type '{0}'.", args.MessageToSend.MessageType));
                        }
                        if (task.IsFaulted)
                        {
                            if (task.Exception != null && task.Exception.InnerExceptions.Count > 0)
                            {
                                args.SocketException = task.Exception.InnerExceptions[0];
                            }
                            else
                            {
                                args.SocketException = new Exception("Unknown socket error.");
                            }
                        }
                        args.Complete();
                    });
                }
                else
                {
                    args.SocketException = new Exception("Connection state is invalid. Please try reconnecting.");
                    args.Complete();
                }
            }
            catch (ObjectDisposedException)
            {
                // Effectively ignoring this
                args.Complete();
            }
            catch (Exception ex)
            {
                args.SocketException =
                    new Exception("Unable to write to the TCP connection. See inner exception for details.", ex);
                args.Complete();
            }
        }
        public void WriteAsync(SocketEventArgs args)
        {
            if (_socket == null)
            {
                args.SocketException = new InvalidOperationException("No server connection has been established.");
                args.Complete();
                return;
            }

            try
            {
                // Write data to the socket
                var writer = new DataWriter(_socket.OutputStream);
                writer.WriteBytes(args.MessageToSend.Serialize());
                writer.StoreAsync().Completed += (info, status) =>
                {
                    writer.DetachStream();
                    writer.Dispose();

                    if (args.MessageToSend is IMqttIdMessage)
                    {
                        var msgWithId = args.MessageToSend as IMqttIdMessage;
                        _logger.LogMessage("Socket", LogLevel.Verbose, string.Format("Sent message type '{0}', ID={1} to server.", msgWithId.MessageType, msgWithId.MessageId));
                    }
                    else
                    {
                        _logger.LogMessage("Socket", LogLevel.Verbose, string.Format("Sent message type '{0}' to server.", args.MessageToSend.MessageType));
                    }

                    if (info.Status == AsyncStatus.Error)
                    {
                        args.SocketException = info.ErrorCode;
                    }
                    args.Complete();
                };
            }
            catch (Exception ex)
            {
                args.SocketException = ex;
                args.Complete();
            }
        }
        public void ConnectAsync(string ipOrHost, int port, SocketEventArgs args)
        {
            var t = new Thread(() =>
            {
                IPEndPoint ep;
                try
                {
                    ep = ResolveIpAddress(ipOrHost, port);
                }
                catch (Exception ex)
                {
                    args.SocketException = ex;
                    args.AdditionalErrorInfo = "Unable to resolve ip address or host name.";
                    args.Complete();
                    return;
                }

                _encryptionLevel = GetSslProtocol(args.EncryptionLevel);
                _clientUid = args.ClientUid;

                try
                {
                    CreateSocketAndConnect(ep);
                    StartReceiving();
                }
                catch (Exception ex)
                {
                    _clientUid = null;
                    args.SocketException = ex;
                }
                finally
                {
                    args.Complete();
                }
            });

            // Start the writer thread
            _writerThread = new Thread(WriteMessageWorker);
            _writerThread.Start();

            // Go connect
            t.Start();
        }
Example #17
0
        public void ConnectAsync(string ipOrHost, int port, SocketEventArgs args)
        {
            CFReadStream  cfRead;
            CFWriteStream cfWrite;

            CFStream.CreatePairWithSocketToHost(ipOrHost, port, out cfRead, out cfWrite);

            // Toll-Free binding from CFStream to a NSStream.
            var inStream  = (NSInputStream)ObjCRuntime.Runtime.GetNSObject(cfRead.Handle);
            var outStream = (NSOutputStream)ObjCRuntime.Runtime.GetNSObject(cfWrite.Handle);
            var pair      = new NSStreamPair(inStream, outStream);

            inStream.Schedule(_socketWorker.RunLoop, NSRunLoop.NSDefaultRunLoopMode);
            outStream.Schedule(_socketWorker.RunLoop, NSRunLoop.NSDefaultRunLoopMode);

            if (args.EncryptionLevel != SocketEncryption.None)
            {
                SetEncryptionOnStreams(args.EncryptionLevel, inStream, outStream);
            }

            var inReady  = false;
            var outReady = false;

            Action complete = () =>
            {
                _socketWorker.ConnectTcpClient(pair, port, args.EncryptionLevel, args.ClientUid);
                args.Complete();
            };

            EventHandler <NSStreamEventArgs> inReadyHandler = null;

            inReadyHandler = (_, e) =>
            {
                inStream.OnEvent -= inReadyHandler;
                inReady           = true;

                if (inReady && outReady)
                {
                    complete();
                }
            };

            EventHandler <NSStreamEventArgs> outReadyHandler = null;

            outReadyHandler = (_, e) =>
            {
                outStream.OnEvent -= outReadyHandler;
                outReady           = true;

                if (inReady && outReady)
                {
                    complete();
                }
            };

            inStream.OnEvent  += inReadyHandler;
            outStream.OnEvent += outReadyHandler;

            inStream.Open();
            outStream.Open();
        }