/// <summary> /// Transmits the UDP ping or ping reply message configured for this instance of NiawaAdHocNetworkAdapter. /// </summary> /// <param name="isReplyMessage">True if ping reply message; False if ping message</param> public void TransmitPingMessage(bool isReplyMessage, string replySerialID) { try { if(!isReplyMessage ) { logger.Info("[" + _description + "-M] Transmitting ping message"); //send message _evtRaiser.RaiseEvent("Message", "Transmitting ping message", null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.MessageCount += 1; /*broadcast UDP ping when requested by implementor*/ if (!_started) throw new Exception("[" + _description + "-M] Could not transmit ping message: NiawaAdHocNetworkAdapter is not started"); if (_tcpHandshakePort == 0) throw new Exception("[" + _description + "-M] Could not transmit ping message: HandshakePort [" + _tcpHandshakePort + "] is not valid."); //create message MessageContent.PingMessageContent pingMessage = new MessageContent.PingMessageContent(_ipAddress, _hostname, string.Empty); NiawaNetDatagram message = new NiawaNetDatagram(_ipAddress, _udpPort, Guid.NewGuid(), _hostname, _applicationName, MessageContent.PingMessageContent.MESSAGE_CONTENT_TYPE_PING, pingMessage.ToJson()); //send message _udpTransmitter.SendMessage(message); } else { logger.Info("[" + _description + "-M] Transmitting ping reply message"); //send message _evtRaiser.RaiseEvent("Message", "Transmitting ping reply message", null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.MessageCount += 1; /*broadcast UDP ping reply when requested by implementor*/ if (!_started) throw new Exception("[" + _description + "-M] Could not transmit ping reply message: NiawaAdHocNetworkAdapter is not started"); if (_tcpHandshakePort == 0) throw new Exception("[" + _description + "-M] Could not transmit ping reply message: HandshakePort [" + _tcpHandshakePort + "] is not valid."); //create message MessageContent.PingMessageContent pingMessage = new MessageContent.PingMessageContent(_ipAddress, _hostname, replySerialID); NiawaNetDatagram message = new NiawaNetDatagram(_ipAddress, _udpPort, Guid.NewGuid(), _hostname, _applicationName, MessageContent.PingMessageContent.MESSAGE_CONTENT_TYPE_PINGREPLY, pingMessage.ToJson()); //send message _udpTransmitter.SendMessage(message); } } catch (Exception ex) { logger.Error("[" + _description + "-M] Error while transmitting ping/ping reply message: " + ex.Message, ex); throw ex; } }
/// <summary> /// Raises event with current status /// </summary> /// <returns></returns> /*public string RaiseStatusReport() { try { if (_started) { _evtRaiser.RaiseEvent("StatusReport", "Started", string.Empty); return "Started"; } else { _evtRaiser.RaiseEvent("StatusReport", "Stopped", string.Empty); return "Stopped"; } } catch (Exception ex) { logger.ErrorException("[" + _description + "-M] Error while raising status report: " + ex.Message, ex); throw ex; } } */ /// <summary> /// Raises an event with thread health information passed in by the caller. This function is utilized in the ThreadHealthMonitor object. /// </summary> /// <param name="description"></param> /// <param name="threadHealthValue"></param> /// <param name="healthFailed"></param> /*public void RaiseThreadHealth(string description, double threadHealthValue, bool healthFailed) { try { _evtRaiser.RaiseEvent("ThreadHealth", "Description:" + description + ";TheadHealth:" + threadHealthValue.ToString("F") + ";HealthFailed:" + healthFailed.ToString(), string.Empty); } catch (Exception ex) { logger.ErrorException("[" + _description + "-M] Error while raising thread health: " + ex.Message, ex); throw ex; } } */ /// <summary> /// Transmits the UDP handshake message configured for this instance of NiawaAdHocNetworkAdapter. /// </summary> public void TransmitHandshakeMessage() { try { logger.Info("[" + _description + "-M] Transmitting handshake message"); //send message _evtRaiser.RaiseEvent("Message", "Transmitting handshake message", null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.MessageCount += 1; /*broadcast UDP handshake when requested by implementor*/ if (!_started) throw new Exception("[" + _description + "-M] Could not transmit handshake message: NiawaAdHocNetworkAdapter is not started"); if (_tcpHandshakePort == 0) throw new Exception("[" + _description + "-M] Could not transmit handshake message: HandshakePort [" + _tcpHandshakePort + "] is not valid."); //create message MessageContent.HandshakeMessageContent handshakeMessage = new MessageContent.HandshakeMessageContent(_ipAddress, _hostname, _tcpHandshakePort); //handshakeMessage.IpAddress = _ipAddress; //handshakeMessage.Hostname = _hostname; //handshakeMessage.HandshakePort = _tcpHandshakePort; NiawaNetDatagram message = new NiawaNetDatagram(_ipAddress, _udpPort, Guid.NewGuid(), _hostname, _applicationName, MessageContent.HandshakeMessageContent.MESSAGE_CONTENT_TYPE, handshakeMessage.ToJson()); //send message _udpTransmitter.SendMessage(message); } catch (Exception ex) { logger.Error("[" + _description + "-M] Error while transmitting handshake message: " + ex.Message, ex); throw ex; } }
//public UdpTransmitter(int port, Niawa.MsEventController.EventConsumer evtConsumer, Niawa.Utilities.UtilsServiceBus utilsBus, string applicationNameDetailed, Niawa.Utilities.SerialId parentThreadId) //{ // try // { // _applicationNameDetailed = applicationNameDetailed; // _port = port; // _evtConsumer = evtConsumer; // _sendQueue = new Queue<NiawaNetDatagram>(); // lockSection = new System.Threading.Semaphore(1, 1); // _description = "UdpTransmitter " + _port.ToString(); // //initialize the endpoints // _groupEndpoint = new System.Net.IPEndPoint(System.Net.IPAddress.Broadcast, _port); // _localEP = new System.Net.IPEndPoint(System.Net.IPAddress.Loopback, _port); // //initialize serial ID generator // id = utilsBus.InitializeSerialId(Niawa.Utilities.IdGeneratorUtils.ID_ROOT_NIAWA_NET_DATAGRAM); // //initialize event logging // _evtRaiser = new MsEventController.EventRaiser("UdpTransmitter", _applicationNameDetailed, _description, utilsBus); // if (_evtConsumer != null) _evtRaiser.AddEventConsumer(_evtConsumer); // _threadStatus = new Niawa.Threading.ThreadStatus(_description, 60, utilsBus.InitializeSerialId(Niawa.Utilities.IdGeneratorUtils.ID_ROOT_NIAWA_THREAD_ID), parentThreadId, _evtRaiser); // //thread status // _threadStatus.Status = Niawa.Threading.ThreadStatus.STATUS_INITIALIZED; // //add thread elective properties. // _threadStatus.AddElectiveProperty("Port", _port.ToString()); // } // catch (Exception ex) // { // logger.Error("[UdpTransmitter-M] Error while instantiating: " + ex.Message, ex); // throw ex; // } //} /// <summary> /// Send UDP message. /// </summary> /// <param name="message">Message to send via UDP.</param> public void SendMessage(NiawaNetDatagram message) { try { if (!_threadStatus.IsThreadEnabled || !_threadStatus.IsThreadActive) { _evtRaiser.RaiseEvent("MessageError", "Cannot send message - Transmitter is not active" , Niawa.Utilities.InlineSortedListCreator.CreateStrStr("NiawaNetMessage", message.ToJson()) , _threadStatus.NodeID , _threadStatus.ParentNodeID); throw new MessageNotSentException("Cannot send message - transmitter is not active"); } //get next serial ID id = Niawa.Utilities.IdGeneratorUtils.IncrementSerialId(id); message.SerialID = id.ToString(); logger.Info("[" + _description + "-M] Queueing message: Type [" + message.MessageType + "] SerialID [" + message.SerialID + "]"); _sendQueue.Enqueue(message); } catch (Exception ex) { logger.Error("[" + _description + "-M] Error while sending message: " + ex.Message, ex); throw ex; } }
/// <summary> /// Transmit message via UDP. /// </summary> /// <param name="message">Message to send via UDP.</param> /// <returns></returns> private bool TransmitMessage(NiawaNetDatagram message) { bool succeeded = false; //attempt lock bool tryLock = lockSection.WaitOne(60000); if (!tryLock) throw new TimeoutException("[" + _description + "-T] Could not obtain lock while sending message"); try { Byte[] messageBytes = message.ToByteArray(); //send message /*v1*/ //_netUdpClient.Connect(_groupEndpoint); //_netUdpClient.Send(messageBytes, messageBytes.Length, _localEP); //_netUdpClient.Close(); //_netUdpClient = null; //messageInProgressGuid = string.Empty; /*v2*/ //_netUdpClient.Send(messageBytes, messageBytes.Length, _localEP); /*v3*/ if (messageBytes.Length > 65000) { //message is too long throw new InvalidOperationException("UdpTransmitter cannot send a message with length greater than 65000 bytes."); } else { bool tryLock2 = lockSentMessageGuidBuffer.WaitOne(5000); if (tryLock2 == false) throw new TimeoutException("Could not obtain lock on Sent Message GUID Buffer while sending message."); try { //add guid to sent buffer _sentMessageGuidBuffer.Add(message.Guid); if (_sentMessageGuidBuffer.Count > 1000) _sentMessageGuidBuffer.RemoveAt(0); } finally { lockSentMessageGuidBuffer.Release(); } //send _netUdpClient.Send(messageBytes, messageBytes.Length); } succeeded = true; } catch (Exception ex) { logger.Error("[" + _description + "-M] Error while transmitting message: " + ex.Message, ex); throw ex; } finally { //release lock lockSection.Release(); } logger.Info("[" + _description + "-T] Message sent: Type [" + message.MessageType + "] SerialID [" + message.SerialID + "] Guid [" + message.Guid.ToString() + "]"); _evtRaiser.RaiseEvent("Message", "Message sent [" + message.SerialID + "]" , Niawa.Utilities.InlineSortedListCreator.CreateStrStr("NiawaNetMessage", message.ToJson()) , _threadStatus.NodeID , _threadStatus.ParentNodeID); _threadStatus.MessageCount += 1; return succeeded; }
/// <summary> /// Loop thread that reads UDP messages and adds items to the receive queue. /// </summary> /// <param name="data"></param> private void ListenThreadImpl(object data) { _threadStatus.IsThreadActive = true; logger.Info("[" + _description + "-T] Receiver active"); bool suspendedStateDetectChange = false; try { while (_threadStatus.IsThreadEnabled) { _threadStatus.ThreadHealthDate = DateTime.Now; //listening if (suspendedStateDetectChange != _threadSuspended) { suspendedStateDetectChange = _threadSuspended; if (_threadSuspended == true) { logger.Info("[" + _description + "-T] Receiver suspended"); } if (_threadSuspended == false) { logger.Info("[" + _description + "-T] Receiver resumed"); } } if (_threadSuspended) { //suspended //logger.Debug("[" + _description + "] Receiver suspended"); System.Threading.Thread.Sleep(10); } else { //not suspended bool receivingMessage = false; try { logger.Info("[" + _description + "-T] Waiting for network data"); //get datagram /*v2*/ //Byte[] recvBytes = _netUdpClient.Receive(ref _recvEndpoint); /*v3*/ Byte[] recvBytes = new Byte[65000]; int ix = _netUdpClient.Receive(recvBytes); Array.Resize<Byte>(ref recvBytes, ix); logger.Info("[" + _description + "-T] Received network data"); receivingMessage = true; NiawaNetDatagram message; //get message contents message = new NiawaNetDatagram(recvBytes); //check if message should be ignored if (_ignoreTransmittedUdpMessages && _udpTransmitter != null && _udpTransmitter.SentMessageGuidBufferContainsGuid(message.Guid)) { //ignore message logger.Info("[" + _description + "-T] Ignoring message sent by associated UdpTransmitter: Type [" + message.MessageType + "] SerialID [" + message.SerialID + "]"); } else { //don't ignore message //attempt lock bool tryLock = lockSection.WaitOne(60000); if (!tryLock) throw new TimeoutException("[" + _description + "-T] Could not obtain lock while receiving message"); try { //add message to queue _receiveQueue.Enqueue(message); } finally { //release lock lockSection.Release(); } //raise event _threadStatus.MessageCount += 1; logger.Info("[" + _description + "-T] Received message: Type [" + message.MessageType + "] SerialID [" + message.SerialID + "]"); _evtRaiser.RaiseEvent("Message", "Received message [" + message.SerialID + "]" , Niawa.Utilities.InlineSortedListCreator.CreateStrStr("NiawaNetMessage", message.ToJson()) , _threadStatus.NodeID , _threadStatus.ParentNodeID); } receivingMessage = false; } catch (System.Threading.ThreadAbortException) // ex1) { //thread was aborted if (receivingMessage == true) { logger.Error("[" + _description + "-T] Could not receive message: Thread aborted"); _evtRaiser.RaiseEvent("MessageError", "Cannot receive message - Thread aborted", null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.MessageErrorCount += 1; } else { logger.Debug("[" + _description + "-T] Thread aborted"); } break; } catch (System.Threading.ThreadInterruptedException) // ex1) { //thread was interrupted if (receivingMessage == true) { logger.Error("[" + _description + "-T] Could not receive message: Thread interrupted"); _evtRaiser.RaiseEvent("MessageError", "Cannot receive message - Thread interrupted", null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.MessageErrorCount += 1; } else { logger.Debug("[" + _description + "-T] Thread interrupted"); } break; } catch (System.Net.Sockets.SocketException ex2) { //socket exception if (ex2.Message.Contains("A blocking operation was interrupted by a call to WSACancelBlockingCall")) { if (receivingMessage == true) { logger.Error("[" + _description + "-T] Could not receive message: Blocking operation interrupted"); _evtRaiser.RaiseEvent("MessageError", "Cannot receive message - Blocking operation interrupted", null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.MessageErrorCount += 1; } else { logger.Debug("[" + _description + "-T] Blocking operation interrupted"); } } else { if (receivingMessage == true) { logger.Error("[" + _description + "-T] Could not receive message: Socket error [" + ex2.Message + "]", ex2); _evtRaiser.RaiseEvent("MessageError", "Cannot receive message - Socket error while receiving message: " + ex2.Message, null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.MessageErrorCount += 1; } else { logger.Debug("[" + _description + "-T] Socket error [" + ex2.Message + "]"); } } } catch (Exception ex) { //exception if (receivingMessage == true) { logger.Error("[" + _description + "-T] Could not receive message: Error [" + ex.Message + "]", ex); _evtRaiser.RaiseEvent("Error", "Cannot receive message - Error while receiving message: " + ex.Message, null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.ErrorCount += 1; _evtRaiser.RaiseEvent("MessageError", "Cannot receive message - Error while receiving message: " + ex.Message, null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.MessageErrorCount += 1; } else { logger.Warn("[" + _description + "-T] Error while receiving messages [" + ex.Message + "]"); } System.Threading.Thread.Sleep(100); } System.Threading.Thread.Sleep(10); } } //done with ListenThread (stopped) } catch (Exception ex) { logger.Error("[" + _description + "-T] Error in listen thread: " + ex.Message, ex); _evtRaiser.RaiseEvent("Error", "[" + _description + "-T] Error in listen thread: " + ex.Message, null, _threadStatus.NodeID, _threadStatus.ParentNodeID); _threadStatus.ErrorCount += 1; throw ex; } finally { _threadStatus.IsThreadActive = false; _threadSuspended = false; _threadStatus.IsThreadEnabled = false; logger.Info("[" + _description + "-T] Receiver inactive"); } }