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 ConnectAsync(MqttConnectMessageBuilder bldr, string ipOrHost, int port, SocketEncryption encryption, object eventData) { var args = new SocketEventArgs { EncryptionLevel = encryption, ClientUid = GenerateClientUid(bldr) }; args.OnOperationComplete((eventArgs) => { OnTcpConnectAsyncCompleted(eventArgs, eventData); if (eventArgs.SocketException == null) { SendMessageAsync(bldr, eventData, eventArgs.ClientUid); } else { FireConnectComplete(new MqttNetEventArgs { Message = bldr.GetMessage(), Exception = eventArgs.SocketException, AdditionalErrorInfo = eventArgs.AdditionalErrorInfo, EventData = eventData, ClientUid = args.ClientUid }); } }); Socket.ConnectAsync(ipOrHost, port, args); }
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(); }
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); }
protected override void OnTcpConnectAsyncCompleted(SocketEventArgs eventArgs, object eventData) { if (eventArgs.SocketException == null) { _clientUid = eventArgs.ClientUid; // In case the client changed global settings, refresh the timeouts on every connect _keepAliveTimer.Reset(MqttProtocolInformation.Settings.KeepAliveTime); } }
public SocketEventArgs Clone() { var arg = new SocketEventArgs(); arg._completedHandler = _completedHandler; arg.SocketException = SocketException; arg.MessageToSend = MessageToSend; arg.AdditionalErrorInfo = AdditionalErrorInfo; arg.ClientUid = ClientUid; arg.EncryptionLevel = EncryptionLevel; return arg; }
public SocketEventArgs Clone() { var arg = new SocketEventArgs(); arg._completedHandler = _completedHandler; arg.SocketException = SocketException; arg.MessageToSend = MessageToSend; arg.AdditionalErrorInfo = AdditionalErrorInfo; arg.ClientUid = ClientUid; arg.EncryptionLevel = EncryptionLevel; return(arg); }
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(); } }
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) { if (_socket == null) { args.SocketException = new InvalidOperationException("No server connection has been established."); FireOnCompletedNewThread(args); return; } int waitResult = WaitHandle.WaitAny(new WaitHandle[] { _stopEvent, _writerThreadReady }, MqttProtocolInformation.Settings.NetworkTimeout * 1000, false); if (waitResult == WaitHandle.WaitTimeout || waitResult == 0) { args.SocketException = new Exception("Unable to send message type " + args.MessageToSend.MessageType + ". Client may be disconnecting."); FireOnCompletedNewThread(args); return; } _writerEventArgs = args; _writerThreadWrite.Set(); }
/// <summary> /// Let derived classes handle the ConnectAsyncComplete callback. /// </summary> /// <param name="eventArgs"></param> /// <param name="eventData"></param> /// <returns></returns> protected virtual void OnTcpConnectAsyncCompleted(SocketEventArgs eventArgs, object eventData) { }
public void WriteAsync(SocketEventArgs args) { _socketWorker.WriteAsync(args); }
public void ConnectAsync(string ipAddress, int port, SocketEventArgs args) { _isConnected = true; 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 SendMessageAsync(IMqttMessage msg, object eventData, string clientUid) { Logger.LogMessage("Protocol", LogLevel.Verbose, "SendMessageAsync(" + msg.MessageType + ")"); var args = new SocketEventArgs { MessageToSend = msg, ClientUid = clientUid }; // If we expect a response, push the event data on our stack and retrieve it with the response if (args.MessageToSend.ExpectedResponse != MessageType.None) { _messageStore.Add(args.MessageToSend, eventData, clientUid); } args.OnOperationComplete((eventArgs) => { MessageType messageType = eventArgs.MessageToSend.MessageType; string exceptionText = eventArgs.SocketException == null ? "Success." : "Error: " + eventArgs.SocketException.ToString(); Logger.LogMessage("Protocol", LogLevel.Verbose, "SendMessageAsync(" + messageType + ") completed callback. " + exceptionText); if (eventArgs.SocketException != null) { // Clean up pending message queue _messageStore.Remove(args.MessageToSend.ExpectedResponse, MqttMessageBase.GetMessageIdOrDefault(args.MessageToSend), clientUid); } OnSendMessageAsyncCompleted(clientUid, eventArgs.MessageToSend, eventArgs.SocketException); if (messageType == MessageType.Connect && eventArgs.SocketException != null) { FireConnectComplete(new MqttNetEventArgs { Message = args.MessageToSend, Exception = eventArgs.SocketException, AdditionalErrorInfo = eventArgs.AdditionalErrorInfo, EventData = eventData, ClientUid = clientUid }); } else if (messageType == MessageType.Disconnect) { CloseConnection(clientUid); FireSendMessageComplete(new MqttNetEventArgs { Message = args.MessageToSend, Exception = eventArgs.SocketException, AdditionalErrorInfo = eventArgs.AdditionalErrorInfo, EventData = eventData, ClientUid = clientUid }); } else if (messageType == MessageType.Subscribe && eventArgs.SocketException != null) { FireSubscribeMessageComplete(new MqttNetEventArgs { Message = args.MessageToSend, Exception = eventArgs.SocketException, AdditionalErrorInfo = eventArgs.AdditionalErrorInfo, EventData = eventData, ClientUid = clientUid }); } else if (args.MessageToSend.ExpectedResponse == MessageType.None || eventArgs.SocketException != null) { FireSendMessageComplete(new MqttNetEventArgs { Message = args.MessageToSend, Exception = eventArgs.SocketException, AdditionalErrorInfo = eventArgs.AdditionalErrorInfo, EventData = eventData, ClientUid = clientUid }); } }); Socket.WriteAsync(args); }
private void FireOnCompletedNewThread(SocketEventArgs args) { var t = new Thread(args.Complete); t.Start(); }
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 WriteAsync(SocketEventArgs args) { if (_socket == null) { args.SocketException = new InvalidOperationException("No server connection has been established."); FireOnCompletedNewThread(args); return; } int waitResult = WaitHandle.WaitAny(new WaitHandle[] {_stopEvent, _writerThreadReady}, MqttProtocolInformation.Settings.NetworkTimeout*1000, false); if (waitResult == WaitHandle.WaitTimeout || waitResult == 0) { args.SocketException = new Exception("Unable to send message type " + args.MessageToSend.MessageType + ". Client may be disconnecting."); FireOnCompletedNewThread(args); return; } _writerEventArgs = args; _writerThreadWrite.Set(); }
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(); }