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); }
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(); } }
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); }
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 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(); }
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(); }); }
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; } }
public void ConnectAsync(string ipAddress, int port, SocketEventArgs args) { _isConnected = true; args.Complete(); }
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 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(); }