예제 #1
0
 /// <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);
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        /// <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);
                }
            }
        }
예제 #11
0
 private void OnCoAPError(Exception e, AbstractCoAPMessage associatedMsg)
 {
     throw new NotImplementedException();
 }
예제 #12
0
 /// <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);
        }
예제 #14
0
 /// <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);
                }
            }
        }
예제 #18
0
 /// <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();
 }