/// <summary> /// Handle error /// </summary> /// <param name="e">The exception that occurred</param> /// <param name="associatedMsg">The associated message (if any)</param> private static void OnCoAPError(Exception e, AbstractCoAPMessage associatedMsg) { if (e.GetType() == typeof(UndeliveredException)) { //Some CON message never got delivered... CoAPRequest undeliveredCONReq = (CoAPRequest)associatedMsg; //Now take action on this underlivered request } }
/// <summary> /// Add message to wait queue /// </summary> /// <param name="coapMsg">AbstractCoAPMessage</param> public void AddToWaitQ(AbstractCoAPMessage coapMsg) { if (coapMsg == null) throw new ArgumentNullException("CoAP message cannot be null and must be of type CON"); if (coapMsg.MessageType.Value != CoAPMessageType.CON) throw new ArgumentException("CoAP message to be added to wait queue must be of type CON"); this._waitEvent.WaitOne();//Wait for thread to release the queue this._conMessageQ.Add(coapMsg); this._waitEvent.Set();//Now allow others to work on the queue }
/// <summary> /// Once a confirmable message is sent, it must wait for an ACK or RST /// If nothing comes within the timeframe, this event is raised. /// </summary> /// <param name="coapMsg">An instance of AbstractCoAPMessage</param> private void OnTimedOutWaitingForResponse(AbstractCoAPMessage coapMsg) { //make an attempt to retransmit coapMsg.RetransmissionCount++; if (coapMsg.RetransmissionCount > this.MaxRetransmissions) { //Exhausted max retransmit this.HandleError(new UndeliveredException("Cannot deliver message. Exhausted retransmit attempts"), coapMsg); } else { coapMsg.Timeout = (int)(coapMsg.RetransmissionCount * this.AckTimeout * AbstractCoAPChannel.DEFAULT_ACK_RANDOM_FACTOR); //attempt resend this.Send(coapMsg); } }
/// <summary> /// Handle error conditions during CoAP exchange /// </summary> /// <param name="ex">The exception that occurred</param> /// <param name="coapMsg">The CoAP message</param> protected void HandleError(Exception ex, AbstractCoAPMessage coapMsg) { CoAPErrorHandler errHandler = CoAPError; try { if (errHandler != null) { errHandler(ex, coapMsg); } } catch (Exception e) { AbstractLogUtil.GetLogger().LogError(e.ToString()); //Do nothing else...do not want to bring down the whole thing because handler failed } }
/// <summary> /// Send the CoAP message to client /// </summary> /// <param name="coapMsg">The CoAP message to send</param> /// <returns>Number of bytes sent</returns> public override int Send(AbstractCoAPMessage coapMsg) { if (coapMsg == null) { throw new ArgumentNullException("Message is NULL"); } if (this._socket == null) { throw new InvalidOperationException("CoAP server not yet started"); } int bytesSent = 0; try { //We do not want server to die when a socket send error occurs... //just clean all settings specific to the remote client and //keep going byte[] coapBytes = coapMsg.ToByteStream(); bytesSent = this._socket.SendTo(coapBytes, coapMsg.RemoteSender); if (coapMsg.MessageType.Value == CoAPMessageType.CON) { //confirmable message...need to wait for a response coapMsg.DispatchDateTime = DateTime.Now; this._msgPendingAckQ.AddToWaitQ(coapMsg); } } catch (Exception e) { this._msgPendingAckQ.RemoveFromWaitQ(coapMsg.ID.Value); if (coapMsg.GetType() == typeof(CoAPRequest)) { CoAPRequest coapReq = (CoAPRequest)coapMsg; this._observers.RemoveResourceObserver(coapReq.GetURL(), coapReq.Token.Value); } else if (coapMsg.GetType() == typeof(CoAPResponse)) { CoAPResponse coapResp = (CoAPResponse)coapMsg; this._observers.RemoveResourceObserver(coapResp); } this.HandleError(e, coapMsg); } return(bytesSent); }
/// <summary> /// Send a CoAP message to the server /// </summary> /// <param name="coapMsg">The CoAP message to send to server</param> /// <returns>Number of bytes sent</returns> public override int Send(AbstractCoAPMessage coapMsg) { if (coapMsg == null) { throw new ArgumentNullException("Message is NULL"); } if (this._clientSocket == null) { throw new InvalidOperationException("CoAP client not yet started"); } int bytesSent = 0; try { byte[] coapBytes = coapMsg.ToByteStream(); if (coapBytes.Length > AbstractNetworkUtils.GetMaxMessageSize()) { throw new UnsupportedException("Message size too large. Not supported. Try block option"); } bytesSent = this._clientSocket.Send(coapBytes); if (coapMsg.MessageType.Value == CoAPMessageType.CON) { //confirmable message...need to wait for a response if (coapMsg.Timeout <= 0) { coapMsg.Timeout = AbstractCoAPChannel.DEFAULT_ACK_TIMEOUT_SECS; } coapMsg.DispatchDateTime = DateTime.Now; this._msgPendingAckQ.AddToWaitQ(coapMsg); } } catch (Exception e) { this._msgPendingAckQ.RemoveFromWaitQ(coapMsg.ID.Value); this.HandleError(e, coapMsg); } return(bytesSent); }
/// <summary> /// Get the request message that was pending response /// </summary> /// <param name="msgId">The message Id corresponding to the message that needs to be extracted</param> /// <returns>A copy of the request object pending response (if found), else null</returns> public CoAPRequest GetRequestPendingResponse(UInt16 msgId) { this._waitEvent.WaitOne();//Wait for thread to release the queue CoAPRequest foundReq = null; try { int count = 0; for (count = 0; count < this._conMessageQ.Count; count++) { AbstractCoAPMessage coapMsgInQ = (AbstractCoAPMessage)this._conMessageQ[count]; if (coapMsgInQ.ID.Value == msgId) { /*Found*/ foundReq = new CoAPRequest(coapMsgInQ.MessageType.Value, coapMsgInQ.Code.Value, coapMsgInQ.ID.Value); foreach (CoAPHeaderOption option in coapMsgInQ.Options) { foundReq.AddOption(option.Number, option.Value); } foundReq.Token = coapMsgInQ.Token; foundReq.Payload = coapMsgInQ.Payload; foundReq.RemoteSender = coapMsgInQ.RemoteSender; break; } } } catch (Exception e) { AbstractLogUtil.GetLogger().LogError(e.ToString()); ;; //TOCHECK::nothing for now } finally { this._waitEvent.Set();//Now allow others to work on the queue } return(foundReq); }
/// <summary> /// The thread procedure that continues to poll /// the queue for timeout /// </summary> protected void PollQ() { bool timedOut = false; int count = 0; while (!this._isDone) { Thread.Sleep((int)this._minTimeoutSecs * 1000); this._waitEvent.WaitOne();//Wait for others to release the Q for (count = 0; count < this._conMessageQ.Count; count++) { AbstractCoAPMessage coapMsg = (AbstractCoAPMessage)this._conMessageQ[count]; DateTime timeoutAt = coapMsg.DispatchDateTime.AddSeconds(coapMsg.Timeout); if (timeoutAt < DateTime.Now /*Message timed out*/) { timedOut = true; break;//We process one timeout at a time } } if (timedOut && count < this._conMessageQ.Count) { AbstractCoAPMessage coapMsg = (AbstractCoAPMessage)this._conMessageQ[count]; this._conMessageQ.RemoveAt(count); this._waitEvent.Set();//Release Q count = 0; timedOut = false; if (this.OnResponseTimeout != null) { try { this.OnResponseTimeout(coapMsg); } catch (Exception e) { AbstractLogUtil.GetLogger().LogError(e.ToString()); /*we do not want to crash the Q because client crashed processing*/ } } } this._waitEvent.Set();//Release Q...for all cases } }
/// <summary> /// Called when error occurs /// </summary> /// <param name="e">The exception that occurred</param> /// <param name="associatedMsg">The associated message (if any)</param> private void OnCoAPError(Exception e, AbstractCoAPMessage associatedMsg) { Console.WriteLine(e.Message); //Write your error logic here __Done.Set(); }
/// <summary> /// This is the thread where the socket server will accept client connections and process /// </summary> protected void WaitForConnections() { EndPoint sender = null; byte[] buffer = null; ArrayList previousBytes = new ArrayList(); int bytesRead = 0; byte mType = 0; UInt16 mId = 0; byte[] udpMsg = null; int maxSize = AbstractNetworkUtils.GetMaxMessageSize(); while (!this._isDone) { try { if (this._socket.Available >= 4 /*Min size of CoAP block*/) { sender = new IPEndPoint(IPAddress.Any, 0); buffer = new byte[maxSize * 2]; bytesRead = this._socket.ReceiveFrom(buffer, ref sender); udpMsg = new byte[bytesRead]; Array.Copy(buffer, udpMsg, bytesRead); mType = AbstractCoAPMessage.PeekMessageType(udpMsg); mId = AbstractCoAPMessage.PeekMessageID(udpMsg); if ((mType == CoAPMessageType.CON || mType == CoAPMessageType.NON) && AbstractCoAPMessage.PeekIfMessageCodeIsRequestCode(udpMsg)) { this.ProcessRequestMessageReceived(udpMsg, ref sender); } else { this.ProcessResponseMessageReceived(udpMsg, ref sender); } } else { //Nothing on the socket...wait Thread.Sleep(5000); } } catch (SocketException se) { //Try to re-initialize socket, and proceed only when the socket //is successfully re-initialized this._isDone = !this.ReInitSocket(); this.HandleError(se, null); } catch (ArgumentNullException argEx) { if (mType == CoAPMessageType.CON) { this.RespondToBadCONRequest(mId); } this.HandleError(argEx, null); } catch (ArgumentException argEx) { if (mType == CoAPMessageType.CON) { this.RespondToBadCONRequest(mId); } this.HandleError(argEx, null); } catch (CoAPFormatException fEx) { //Invalid message.. if (mType == CoAPMessageType.CON) { this.RespondToBadCONRequest(mId); } this.HandleError(fEx, null); } } }
private void OnCoAPError(Exception e, AbstractCoAPMessage associatedMsg) { throw new NotImplementedException(); }
/// <summary> /// Called when an error occurs.Not used in this sample /// </summary> /// <param name="e">The exception</param> /// <param name="associatedMsg">Associated message if any, else null</param> static void OnCoAPError(Exception e, AbstractCoAPMessage associatedMsg) { //put error handling code here }
/// <summary> /// Receive a message from the server. This will block if there /// are no messages. Please note, you must handle all errors (except timeout) /// and no error is raised. /// </summary> /// <param name="rxTimeoutMillis"> /// The timeout value in milliseconds.The default value is 0, which indicates an infinite time-out period. /// Specifying -1 also indicates an infinite time-out period /// </param> /// <param name="timedOut">Is set to true on timeout</param> /// <returns>An instance of AbstractCoAPMessage on success, else null on error/timeout</returns> public AbstractCoAPMessage ReceiveMessage(int rxTimeoutMillis, ref bool timedOut) { byte[] buffer = null; int maxSize = AbstractNetworkUtils.GetMaxMessageSize(); CoAPRequest coapReq = null; CoAPResponse coapResp = null; try { this._clientSocket.ReceiveTimeout = rxTimeoutMillis; buffer = new byte[maxSize * 2]; int bytesRead = this._clientSocket.Receive(buffer); byte[] udpMsg = new byte[bytesRead]; Array.Copy(buffer, udpMsg, bytesRead); byte mType = AbstractCoAPMessage.PeekMessageType(udpMsg); if ((mType == CoAPMessageType.CON || mType == CoAPMessageType.NON) && AbstractCoAPMessage.PeekIfMessageCodeIsRequestCode(udpMsg)) { //This is a request coapReq = new CoAPRequest(); coapReq.FromByteStream(udpMsg); coapReq.RemoteSender = this._remoteEP;//Setup who sent this message string uriHost = ((IPEndPoint)this._remoteEP).Address.ToString(); UInt16 uriPort = (UInt16)((IPEndPoint)this._remoteEP).Port; //setup the default values of host and port //setup the default values of host and port if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_HOST)) { coapReq.Options.AddOption(CoAPHeaderOption.URI_HOST, AbstractByteUtils.StringToByteUTF8(uriHost)); } if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_PORT)) { coapReq.Options.AddOption(CoAPHeaderOption.URI_PORT, AbstractByteUtils.GetBytes(uriPort)); } return(coapReq); } else { //This is a response coapResp = new CoAPResponse(); coapResp.FromByteStream(udpMsg); coapResp.RemoteSender = this._remoteEP;//Setup who sent this message return(coapResp); } } catch (SocketException se) { if (se.ErrorCode == (int)SocketError.TimedOut) { timedOut = true; } else { throw se; } } return(null); }
/// <summary> /// Not used in this sample /// </summary> /// <param name="e"></param> /// <param name="associatedMsg"></param> private static void OnCoAPError(Exception e, AbstractCoAPMessage associatedMsg) { }
/// <summary> /// Called when error occurs /// </summary> /// <param name="e">The exception that occurred</param> /// <param name="associatedMsg">The associated message (if any)</param> static void OnCoAPError(Exception e, AbstractCoAPMessage associatedMsg) { //Write your error logic here }
/// <summary> /// Send a message /// </summary> /// <param name="coapMsg">The CoAP message to send</param> /// <returns>The number of bytes sent</returns> public abstract int Send(AbstractCoAPMessage coapMsg);
/// <summary> /// This thread continuously looks for messages on the socket /// Once available, it will post them for handling downstream /// </summary> protected void ProcessReceivedMessages() { byte[] buffer = null; int maxSize = AbstractNetworkUtils.GetMaxMessageSize(); while (!this._isDone) { Thread.Sleep(1000); try { if (this._clientSocket.Available >= 4 /*Min size of CoAP block*/) { buffer = new byte[maxSize * 2]; int bytesRead = this._clientSocket.Receive(buffer); byte[] udpMsg = new byte[bytesRead]; Array.Copy(buffer, udpMsg, bytesRead); byte mType = AbstractCoAPMessage.PeekMessageType(udpMsg); if ((mType == CoAPMessageType.CON || mType == CoAPMessageType.NON) && AbstractCoAPMessage.PeekIfMessageCodeIsRequestCode(udpMsg)) { //This is a request CoAPRequest coapReq = new CoAPRequest(); coapReq.FromByteStream(udpMsg); coapReq.RemoteSender = this._remoteEP;//Setup who sent this message string uriHost = ((IPEndPoint)this._remoteEP).Address.ToString(); UInt16 uriPort = (UInt16)((IPEndPoint)this._remoteEP).Port; //setup the default values of host and port //setup the default values of host and port if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_HOST)) { coapReq.Options.AddOption(CoAPHeaderOption.URI_HOST, AbstractByteUtils.StringToByteUTF8(uriHost)); } if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_PORT)) { coapReq.Options.AddOption(CoAPHeaderOption.URI_PORT, AbstractByteUtils.GetBytes(uriPort)); } this.HandleRequestReceived(coapReq); } else { //This is a response CoAPResponse coapResp = new CoAPResponse(); coapResp.FromByteStream(udpMsg); coapResp.RemoteSender = this._remoteEP;//Setup who sent this message //Remove the waiting confirmable message from the timeout queue if (coapResp.MessageType.Value == CoAPMessageType.ACK || coapResp.MessageType.Value == CoAPMessageType.RST) { this._msgPendingAckQ.RemoveFromWaitQ(coapResp.ID.Value); } this.HandleResponseReceived(coapResp); } } } catch (SocketException se) { //Close this client connection this._isDone = true; this.HandleError(se, null); } catch (ArgumentNullException argEx) { this.HandleError(argEx, null); } catch (ArgumentException argEx) { this.HandleError(argEx, null); } catch (CoAPFormatException fEx) { //Invalid message.. this.HandleError(fEx, null); } } }
/// <summary> /// Called when error occurs /// </summary> /// <param name="e">The exception that occurred</param> /// <param name="associatedMsg">The associated message (if any)</param> private void OnCoAPError(Exception e, AbstractCoAPMessage associatedMsg) { FileLogger.Write(e.Message); __Done.Set(); }