Exemple #1
0
        /// <summary>
        /// Notify listeners of the new temperature
        /// </summary>
        /// <param name="temp">The temperature</param>
        static private void NotifyListeners(int temp)
        {
            ArrayList resObservers = coapServer.ObserversList.GetResourceObservers(OBSERVED_RESOURCE_URI);

            if (resObservers == null || resObservers.Count == 0)
            {
                return;
            }

            //The next observe sequence number
            UInt16 obsSeq = (UInt16)Convert.ToInt16(DateTime.Today.ToString("mmss"));//Will get accomodated in 24-bits limit and will give good sequence

            foreach (CoAPRequest obsReq in resObservers)
            {
                UInt16      mId       = coapServer.GetNextMessageID();
                CoAPRequest notifyReq = new CoAPRequest(CoAPMessageType.CON, CoAPMessageCode.PUT, mId);
                notifyReq.RemoteSender = obsReq.RemoteSender;
                notifyReq.Token        = obsReq.Token;
                //Add observe option with sequence number
                notifyReq.AddOption(CoAPHeaderOption.OBSERVE, AbstractByteUtils.GetBytes(obsSeq));

                //The payload will be JSON
                Hashtable ht = new Hashtable();
                ht.Add("temp", temp);
                string jsonStr = JSONResult.ToJSON(ht);
                notifyReq.AddPayload(jsonStr);
                //Tell recipient about the content-type of the response
                notifyReq.AddOption(CoAPHeaderOption.CONTENT_FORMAT, AbstractByteUtils.GetBytes(CoAPContentFormatOption.APPLICATION_JSON));
                //send it
                coapServer.Send(notifyReq);
            }
        }
Exemple #2
0
        /// <summary>
        /// As bytes...endian ness is taken care of in this method
        /// </summary>
        /// <param name="reserved">Not used now</param>
        /// <returns>byte[]</returns>
        public byte[] ToStream(UInt16 reserved)
        {
            if (this.SequenceNumber <= 0xF)
            {
                //single byte
                byte[] retVal = new byte[1];
                retVal[0] = (byte)this.SequenceNumber;
                retVal[0] = (byte)(retVal[0] << 4);                                      //seq number in top 4 bits
                retVal[0] = (this.HasMoreBlocks) ? (byte)(retVal[0] | 0x08) : retVal[0]; //more flag in 5th bit
                retVal[0] = (byte)(retVal[0] | this.SizeExponent);                       //size exponent, last 3 bits

                return(retVal);
            }
            else if (this.SequenceNumber > 0xF && this.SequenceNumber <= 0xFFF)
            {
                //double byte
                byte[] temp = new byte[2];

                if (AbstractByteUtils.IsTargetLittleEndian())
                {
                    temp    = AbstractByteUtils.GetBytes((UInt16)(this._seqNumber << 4));
                    temp[0] = (this.HasMoreBlocks) ? (byte)(temp[0] | 0x08) : (byte)(temp[0] & 0xF7);
                    temp[0] = (byte)(temp[0] | this.SizeExponent);
                }
                else
                {
                    temp    = AbstractByteUtils.GetBytes((UInt16)(this._seqNumber >> 4));
                    temp[1] = (this.HasMoreBlocks) ? (byte)(temp[1] | 0x08) : (byte)(temp[1] & 0xF7);
                    temp[1] = (byte)(temp[1] | this.SizeExponent);
                }
                return(temp);
            }
            else
            {
                //3 bytes...we start with 4(long) and then return last 3 only
                byte[] temp   = new byte[4];
                byte[] retVal = new byte[3];

                if (AbstractByteUtils.IsTargetLittleEndian())
                {
                    temp    = AbstractByteUtils.GetBytes((UInt64)(this._seqNumber << 4));
                    temp[0] = (this.HasMoreBlocks) ? (byte)(temp[0] | 0x08) : (byte)(temp[0] & 0xF7);
                    temp[0] = (byte)(temp[0] | this.SizeExponent);
                    Array.Copy(temp, 0, retVal, 0, 3);
                }
                else
                {
                    //use the index  =2, index 3 will be discarded
                    temp    = AbstractByteUtils.GetBytes((UInt64)(this._seqNumber >> 4));
                    temp[2] = (this.HasMoreBlocks) ? (byte)(temp[1] | 0x08) : (byte)(temp[1] & 0xF7);
                    temp[2] = (byte)(temp[1] | this.SizeExponent);
                    Array.Copy(temp, 1, retVal, 0, 3);
                }

                return(retVal);
            }
        }
Exemple #3
0
        /// <summary>
        /// Called when a CoAP request is received...we will only support CON requests
        /// of type GET... the path is sensors/temp
        /// </summary>
        /// <param name="coapReq">CoAPRequest object</param>
        private static void OnCoAPRequestReceived(CoAPRequest coapReq)
        {
            string reqPath = (coapReq.GetPath() != null) ? coapReq.GetPath().ToLower() : "";

            if (coapReq.MessageType.Value == CoAPMessageType.CON)
            {
                if (coapReq.Code.Value != CoAPMessageCode.GET)
                {
                    CoAPResponse resp = new CoAPResponse(CoAPMessageType.ACK,
                                                         CoAPMessageCode.METHOD_NOT_ALLOWED,
                                                         coapReq /*Copy all necessary values from request in the response*/);
                    //When you use the constructor that accepts a request, then automatically
                    //the message id , token and remote sender values are copied over to the response
                    coapServer.Send(resp);
                }
                else if (reqPath != "sensors/temp")
                {
                    //We do not understand this..
                    CoAPResponse resp = new CoAPResponse(CoAPMessageType.ACK,
                                                         CoAPMessageCode.NOT_FOUND,
                                                         coapReq /*Copy all necessary values from request in the response*/);
                    coapServer.Send(resp);
                }
                else
                {
                    Debug.WriteLine(coapReq.ToString());
                    CoAPResponse resp = new CoAPResponse(CoAPMessageType.ACK,
                                                         CoAPMessageCode.CONTENT,
                                                         coapReq /*Copy all necessary values from request in the response*/);
                    //The payload will be JSON
                    Hashtable ht = new Hashtable();
                    ht.Add("temp", GetRoomTemperature());
                    string jsonStr = JSONResult.ToJSON(ht);
                    resp.AddPayload(jsonStr);
                    //Tell recipient about the content-type of the response
                    resp.AddOption(CoAPHeaderOption.CONTENT_FORMAT, AbstractByteUtils.GetBytes(CoAPContentFormatOption.APPLICATION_JSON));
                    //send it
                    coapServer.Send(resp);
                }
            }
        }
        /// <summary>
        /// Handle request received from remote clients
        /// </summary>
        /// <param name="msgStream">The byte stream that represents a request message</param>
        /// <param name="sender">The remote sender endpoint</param>
        protected virtual void ProcessRequestMessageReceived(byte[] msgStream, ref EndPoint sender)
        {
            CoAPRequest coapReq      = new CoAPRequest();
            IPEndPoint  remoteSender = (IPEndPoint)sender;

            try
            {
                coapReq.FromByteStream(msgStream);
                coapReq.RemoteSender = new IPEndPoint(remoteSender.Address, remoteSender.Port); //Setup who sent this message

                //setup the default values of host and port
                if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_HOST))
                {
                    coapReq.Options.AddOption(CoAPHeaderOption.URI_HOST, AbstractByteUtils.StringToByteUTF8(this._host));
                }
                if (!coapReq.Options.HasOption(CoAPHeaderOption.URI_PORT))
                {
                    coapReq.Options.AddOption(CoAPHeaderOption.URI_PORT, AbstractByteUtils.GetBytes((UInt16)this._port));
                }

                if (coapReq.MessageType.Value == CoAPMessageType.CON &&
                    coapReq.Code.Value == CoAPMessageCode.EMPTY)
                {
                    //This is a PING..send a RST
                    this.RespondToPing(coapReq);
                }
                else
                {
                    this.HandleRequestReceived(coapReq);//Other messages, let program handle it
                }
            }
            catch
            {
                ;//TOCHECK::Do nothing, we do not want to crash the server just because we
                 //could not process one received message...will check later how to improve this
            }
        }
        /// <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>
 /// Convert this object into a byte stream in network byte order
 /// </summary>
 /// <param name="reserved">Not used now</param>
 /// <returns>byte array</returns>
 public byte[] ToStream(UInt16 reserved)
 {
     byte[] mID = AbstractByteUtils.GetBytes(this.Value);
     mID = AbstractNetworkUtils.ToNetworkByteOrder(mID);
     return(mID);
 }
Exemple #7
0
        /// <summary>
        /// Set the request URL
        /// </summary>
        /// <param name="coapURL">The coap URL associated with the request</param>
        public void SetURL(string coapURL)
        {
            if (coapURL == null || coapURL.Trim().Length == 0)
            {
                throw new ArgumentNullException("Invalid CoAP URL");
            }
            coapURL = coapURL.Trim();

            /*
             * The URI object provided by NETMF does not work if the scheme is not http/https
             * Therefore, after checking for the scheme, we replace it with http
             * and then use the Uri class for other items
             */
            string scheme = AbstractURIUtils.GetUriScheme(coapURL);

            if (scheme == null || (scheme.Trim().ToLower() != "coap" && scheme.Trim().ToLower() != "coaps"))
            {
                throw new ArgumentException("Invalid CoAP URL");
            }
            if (scheme.Trim().ToLower() == "coaps")
            {
                this.IsSecure = true;
            }
            if (coapURL.IndexOf("#") >= 0)
            {
                throw new ArgumentException("Fragments not allowed in CoAP URL");
            }
            //Add these items as option
            //The host
            this.Options.AddOption(CoAPHeaderOption.URI_HOST, AbstractByteUtils.StringToByteUTF8(AbstractURIUtils.GetUriHost(coapURL)));
            //The port
            this.Options.AddOption(CoAPHeaderOption.URI_PORT, AbstractByteUtils.GetBytes((UInt16)AbstractURIUtils.GetUriPort(coapURL)));

            //Path components
            string[] segments = AbstractURIUtils.GetUriSegments(coapURL);

            if (segments != null && segments.Length > 0)
            {
                foreach (string segment in segments)
                {
                    if (segment.Trim().Length == 0)
                    {
                        continue;
                    }
                    this.Options.AddOption(CoAPHeaderOption.URI_PATH, AbstractByteUtils.StringToByteUTF8(AbstractURIUtils.UrlDecode(segment)));
                }
            }
            //Query
            string[] qParams = AbstractURIUtils.GetQueryParameters(coapURL);
            if (qParams != null && qParams.Length > 0)
            {
                foreach (string queryComponent in qParams)
                {
                    if (queryComponent.Trim().Length == 0)
                    {
                        continue;
                    }
                    this.Options.AddOption(CoAPHeaderOption.URI_QUERY, AbstractByteUtils.StringToByteUTF8(AbstractURIUtils.UrlDecode(queryComponent)));
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Called when a CoAP request is received (NON, CON)
        /// </summary>
        /// <param name="coapReq">CoAPRequest object</param>
        private static void OnCoAPRequestReceived(CoAPRequest coapReq)
        {
            string reqPath = (coapReq.GetPath() != null) ? coapReq.GetPath().ToLower() : "";

            /*
             * For well-know path, we should support both CON and NON.
             * For NON request, we send back the details in another NON message
             * For CON request, we send back the details in an ACK
             */
            /*Well known should be a GET*/
            if (coapReq.Code.Value != CoAPMessageCode.GET)
            {
                if (coapReq.MessageType.Value == CoAPMessageType.CON)
                {
                    CoAPResponse resp = new CoAPResponse(CoAPMessageType.ACK,
                                                         CoAPMessageCode.METHOD_NOT_ALLOWED,
                                                         coapReq /*Copy all necessary values from request in the response*/);
                    //When you use the constructor that accepts a request, then automatically
                    //the message id , token and remote sender values are copied over to the response
                    coapServer.Send(resp);
                }
                else
                {
                    //For NON, we can only send back a RST
                    CoAPResponse resp = new CoAPResponse(CoAPMessageType.RST,
                                                         CoAPMessageCode.METHOD_NOT_ALLOWED,
                                                         coapReq /*Copy all necessary values from request in the response*/);
                    //When you use the constructor that accepts a request, then automatically
                    //the message id , token and remote sender values are copied over to the response
                    coapServer.Send(resp);
                }
            }
            else
            {
                //Message type is GET...check the path..this server only supports well-known path
                if (reqPath != ".well-known/core")
                {
                    if (coapReq.MessageType.Value == CoAPMessageType.CON)
                    {
                        CoAPResponse resp = new CoAPResponse(CoAPMessageType.ACK,
                                                             CoAPMessageCode.NOT_FOUND,
                                                             coapReq /*Copy all necessary values from request in the response*/);
                        coapServer.Send(resp);
                    }
                    else
                    {
                        //For NON, we can only send back a RST
                        CoAPResponse resp = new CoAPResponse(CoAPMessageType.RST,
                                                             CoAPMessageCode.NOT_FOUND,
                                                             coapReq /*Copy all necessary values from request in the response*/);
                        coapServer.Send(resp);
                    }
                }
                else
                {
                    //Request is GET and path is right
                    if (coapReq.MessageType.Value == CoAPMessageType.CON)
                    {
                        CoAPResponse resp = new CoAPResponse(CoAPMessageType.ACK,
                                                             CoAPMessageCode.CONTENT,
                                                             coapReq /*Copy all necessary values from request in the response*/);
                        //Add response payload
                        resp.AddPayload(GetSupportedResourceDescriptions());
                        //Tell recipient about the content-type of the response
                        resp.AddOption(CoAPHeaderOption.CONTENT_FORMAT, AbstractByteUtils.GetBytes(CoAPContentFormatOption.APPLICATION_LINK_FORMAT));
                        coapServer.Send(resp);
                    }
                    else
                    {
                        //Its a NON, send a NON back...in CoAPSharp, NON is always considered as request
                        CoAPResponse resp = new CoAPResponse(CoAPMessageType.NON,
                                                             CoAPMessageCode.CONTENT,
                                                             coapReq.ID.Value);
                        //Copy over other needed values from the reqeust
                        resp.Token        = coapReq.Token;
                        resp.RemoteSender = coapReq.RemoteSender;
                        resp.AddPayload(GetSupportedResourceDescriptions());
                        //Tell recipient about the content-type of the response
                        resp.AddOption(CoAPHeaderOption.CONTENT_FORMAT, AbstractByteUtils.GetBytes(CoAPContentFormatOption.APPLICATION_LINK_FORMAT));
                        //send it
                        coapServer.Send(resp);
                    }
                }
            }
        }
Exemple #9
0
 /// <summary>
 /// Get the value as a byte array
 /// </summary>
 /// <returns>byte array</returns>
 public byte[] GetValueAsBytes()
 {
     return(AbstractByteUtils.GetBytes(Value));
 }
Exemple #10
0
        /// <summary>
        /// Convert this option into a byte stream int network byte order
        /// </summary>
        /// <param name="previousOptionNumber">The previous option number in the sequence of options</param>
        /// <returns>byte array</returns>
        public byte[] ToStream(UInt16 previousOptionNumber)
        {
            //The option format is given below

            /*********************************************
            | 4 bits option delta | 4 bits length        |
            |  ----------------------------------------------
            |      0-2 bytes option delta extended       |
            |  ----------------------------------------------
            |      0-2 bytes option length extended      |
            |  ----------------------------------------------
            |               0-* bytes option value       |
            *********************************************/
            int streamLength = 1;
            //Get Option delta
            byte   optionDelta         = 0;
            UInt16 derivedOptionNumber = (UInt16)(this.Number - previousOptionNumber);

            byte[] optionDeltaEx = null;
            if (derivedOptionNumber <= 12)
            {
                optionDelta = (byte)derivedOptionNumber;
            }
            else if (derivedOptionNumber > 12 && derivedOptionNumber <= 255 /*Option number is single byte*/)
            {
                optionDeltaEx = new byte[1] {
                    (byte)(derivedOptionNumber - 13)
                };
                optionDelta = 13;
                streamLength++;//1 additional byte
            }
            else /*Option number is double byte*/
            {
                optionDelta   = 14;
                optionDeltaEx = AbstractByteUtils.GetBytes((UInt16)(derivedOptionNumber - 269));
                optionDeltaEx = AbstractNetworkUtils.ToNetworkByteOrder(optionDeltaEx);
                streamLength += 2; //two additional bytes
            }
            //Get option length
            byte optionLength = 0;

            byte[] optionLengthEx = null;
            if (this.Value != null)
            {
                if (this.Value.Length > 0 && this.Value.Length < 13)
                {
                    optionLength = (byte)this.Value.Length;
                }
                else if (this.Value.Length > 12 && this.Value.Length <= 255)
                {
                    optionLength   = 13;
                    optionLengthEx = new byte[1] {
                        (byte)(this.Value.Length - 13)
                    };
                    streamLength++;//1 additional byte
                }
                else if (this.Value.Length > 255)
                {
                    optionLength   = 14;
                    optionLengthEx = AbstractByteUtils.GetBytes((UInt16)(this.Value.Length - 269));
                    optionLengthEx = AbstractNetworkUtils.ToNetworkByteOrder(optionLengthEx);
                    streamLength  += 2; //two additional bytes
                }
            }
            streamLength += ((this.Value != null && !this.IsEmpty()) ? this.Value.Length : 0);
            byte[] optionStream = new byte[streamLength];
            int    count        = 0;

            optionStream[count++] = (byte)((optionDelta << 4) | (optionLength)); //header + length
            if (optionDelta == 13)                                               //delta extended
            {
                optionStream[count++] = optionDeltaEx[0];
            }
            else if (optionDelta == 14)
            {
                optionStream[count++] = optionDeltaEx[0];
                optionStream[count++] = optionDeltaEx[1];
            }
            if (optionLength == 13)
            {
                optionStream[count++] = optionLengthEx[0];
            }
            else if (optionLength == 14)
            {
                optionStream[count++] = optionLengthEx[0];
                optionStream[count++] = optionLengthEx[1];
            }
            if (this.Value != null && this.Value.Length > 0 && !this.IsEmpty())
            {
                byte[] optionValue = new byte[this.Value.Length];
                Array.Copy(this.Value, optionValue, this.Value.Length);
                if (this.NeedsByteOrdering(this.Number))
                {
                    optionValue = AbstractNetworkUtils.ToNetworkByteOrder(optionValue);
                }
                Array.Copy(optionValue, 0, optionStream, count, optionValue.Length);
            }

            return(optionStream);
        }
        /// <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);
        }