示例#1
0
 /// <summary>
 /// A CoAP token created from string value
 /// </summary>
 /// <param name="tokenValue">The string value that represents the CoAP token</param>
 public CoAPToken(string tokenValue)
 {
     if (tokenValue == null || tokenValue.Trim().Length == 0)
     {
         throw new ArgumentNullException("Token value cannot be NULL or empty string");
     }
     this.Value  = AbstractByteUtils.StringToByteUTF8(tokenValue);
     this.Length = (byte)this.Value.Length;
 }
示例#2
0
 /// <summary>
 /// Creates a payload with string data
 /// </summary>
 /// <param name="payloadData">Payload data as string</param>
 public CoAPPayload(string payloadData)
 {
     if (payloadData == null || payloadData.Trim().Length == 0)
     {
         throw new ArgumentNullException("Payload data cannot be NULL or empty string");
     }
     if (payloadData.Trim().Length > AbstractNetworkUtils.GetMaxMessageSize() / 2)
     {
         throw new ArgumentException("Payload size cannot be more than " + AbstractNetworkUtils.GetMaxMessageSize() / 2);
     }
     this.Value = AbstractByteUtils.StringToByteUTF8(payloadData.Trim());
 }
示例#3
0
 /// <summary>
 /// Add the token value. If the value is larger than 8 bytes, then it is truncated to 8 bytes
 /// The string is treated as UTF-8 string
 /// </summary>
 /// <param name="tokenValue">The token value (maximum 8 bytes)</param>
 public void AddTokenValue(string tokenValue)
 {
     if (this.Token == null)
     {
         this.Token = new CoAPToken();
     }
     if (tokenValue != null)
     {
         byte[] asBytes = AbstractByteUtils.StringToByteUTF8(tokenValue);
         int    len     = (asBytes.Length > 8) ? 8 : asBytes.Length;
         this.Token.Value = new byte[len];
         Array.Copy(asBytes, 0, this.Token.Value, 0, len);
         this.Token.Length = (byte)this.Token.Value.Length;
     }
 }
        /// <summary>
        /// Add a new option to the list of options
        /// </summary>
        /// <param name="optionNumber">The option number</param>
        /// <param name="optionValue">The associated option value as UTF-8string. This will be converted to bytes internally</param>
        public virtual void AddOption(UInt16 optionNumber, string optionValue)
        {
            CoAPHeaderOption headerOption = new CoAPHeaderOption(optionNumber, AbstractByteUtils.StringToByteUTF8(optionValue));

            if (!headerOption.IsRepeatable() && this.HasOption(optionNumber))
            {
                //Specs say that if an option is not repeatable and it still appears multiple times,
                //each subsequent option must be treated as un-recognized....
                //In this implementation, we do not allow non-repetable options to be added to the list
                throw new CoAPFormatException("Non-repeatable option already present in collection. Cannot add more.");
            }
            else
            {
                this.Add(headerOption);
            }
        }
示例#5
0
        /// <summary>
        /// Add the payload...limited to 1024 bytes...we assume the string is in UTF-8 format
        /// </summary>
        /// <param name="payload">A unicode string not longer than 1024 bytes</param>
        public void AddPayload(string payload)
        {
            if (payload == null || payload.Trim().Length == 0)
            {
                return;
            }

            this.Payload = new CoAPPayload();
            byte[] payloadAsUtf8 = AbstractByteUtils.StringToByteUTF8(payload);
            int    length        = payloadAsUtf8.Length;

            //if (length > 1024) length = 1024;

            this.Payload.Value = new byte[length];
            Array.Copy(payloadAsUtf8, 0, this.Payload.Value, 0, length);
        }
        /// <summary>
        /// Set the location URL. This is set by the response to indicate "Created" result if the
        /// request is POST (to create a new resource)
        /// </summary>
        /// <param name="locationURL">The location URL relative to the URI that got created</param>
        public void SetLocation(string locationURL)
        {
            if (locationURL == null || locationURL.Trim().Length == 0)
            {
                throw new ArgumentException("Invalid CoAP location URL");
            }
            locationURL = locationURL.Trim().ToLower();

            if (locationURL.IndexOf("#") >= 0)
            {
                throw new ArgumentException("Fragments not allowed in CoAP location URL");
            }
            //Add these items as option

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

            if (segments != null && segments.Length > 0)
            {
                foreach (string segment in segments)
                {
                    if (segment.Trim().Length == 0)
                    {
                        continue;
                    }
                    this.Options.AddOption(CoAPHeaderOption.LOCATION_PATH, AbstractByteUtils.StringToByteUTF8(AbstractURIUtils.UrlDecode(segment)));
                }
            }
            //Query
            string[] qParams = AbstractURIUtils.GetQueryParameters(locationURL);
            if (qParams != null && qParams.Length > 0)
            {
                foreach (string queryComponent in qParams)
                {
                    if (queryComponent.Trim().Length == 0)
                    {
                        continue;
                    }
                    this.Options.AddOption(CoAPHeaderOption.LOCATION_QUERY, AbstractByteUtils.StringToByteUTF8(AbstractURIUtils.UrlDecode(queryComponent)));
                }
            }
        }
        /// <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);
                }
            }
        }
示例#9
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)));
                }
            }
        }
        /// <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);
        }