One document matched: draft-kovatsch-lwig-class1-coap-00.xml


<?xml version="1.0" encoding="US-ASCII"?>
<!-- This template is for creating an Internet Draft using xml2rfc,
     which is available here: http://xml.resource.org. -->
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!-- One method to get references from the online citation libraries.
     There has to be one entity for each item to be referenced. 
     An alternate method (rfc include) is described in the references. -->
<!ENTITY I-D.ietf-lwig-guidance SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-lwig-guidance.xml">
<!ENTITY I-D.ietf-core-coap SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-core-coap.xml">
<!ENTITY I-D.ietf-core-block SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-core-block.xml">
<!ENTITY I-D.ietf-core-observe SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.ietf-core-observe.xml">
<!ENTITY I-D.vial-core-mirror-proxy SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.vial-core-mirror-proxy.xml">
<!ENTITY I-D.fossati-core-publish-option SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.fossati-core-publish-option.xml">
<!ENTITY I-D.fossati-core-monitor-option SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.fossati-core-monitor-option.xml">
<!ENTITY I-D.rahman-core-sleepy SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.rahman-core-sleepy.xml">
<!ENTITY RFC6550 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6550.xml">
<!ENTITY RFC6570 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6570.xml">
]>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<!-- used by XSLT processors -->
<!-- For a complete list and description of processing instructions (PIs), 
     please see http://xml.resource.org/authoring/README.html. -->
<!-- Below are generally applicable Processing Instructions (PIs) that most I-Ds might want to use.
     (Here they are set differently than their defaults in xml2rfc v1.32) -->
<?rfc strict="yes" ?>
<!-- give errors regarding ID-nits and DTD validation -->
<!-- control the table of contents (ToC) -->
<?rfc toc="yes"?>
<!-- generate a ToC -->
<?rfc tocdepth="4"?>
<!-- the number of levels of subsections in ToC. default: 3 -->
<!-- control references -->
<?rfc symrefs="yes"?>
<!-- use symbolic references tags, i.e, [RFC2119] instead of [1] -->
<?rfc sortrefs="yes" ?>
<!-- sort the reference entries alphabetically -->
<!-- control vertical white space 
     (using these PIs as follows is recommended by the RFC Editor) -->
<?rfc compact="yes" ?>
<!-- do not start each main section on a new page -->
<?rfc subcompact="no" ?>
<!-- keep one blank line between list items -->
<!-- end of list of popular I-D processing instructions -->
<rfc category="info" docName="draft-kovatsch-lwig-class1-coap-00"
     ipr="trust200902">
  <!-- category values: std, bcp, info, exp, and historic
     ipr values: full3667, noModification3667, noDerivatives3667
     you can add the attributes updates="NNNN" and obsoletes="NNNN" 
     they will automatically be output with "(if approved)" -->

  <!-- ***** FRONT MATTER ***** -->

  <front>
    <!-- The abbreviated title is used in the page header - it is only necessary if the 
         full title is longer than 39 characters -->

    <title abbrev="">Implementing CoAP for Class 1 Devices</title>

    <!-- add 'role="editor"' below for the editors if appropriate -->

    <!-- Another author who claims to be an editor -->

    <author fullname="Matthias Kovatsch" initials="M." surname="Kovatsch">
      <organization>ETH Zurich</organization>

      <address>
        <postal>
          <street>Universitätstrasse 6</street>

          <!-- Reorder these if your country does things differently -->

          <city>Zurich</city>

          <region/>

          <code>CH-8092</code>

          <country>Switzerland</country>
        </postal>

        <phone>+41 44 632 06 87</phone>

        <email>kovatsch@inf.ethz.ch</email>

        <!-- uri and facsimile elements may also be added -->
      </address>
    </author>

    <date day="15" month="October" year="2012"/>

    <!-- If the month and year are both specified and are the current ones, xml2rfc will fill 
         in the current day for you. If only the current year is specified, xml2rfc will fill 
	 in the current day and month for you. If the year is not the current one, it is 
	 necessary to specify at least a month (xml2rfc assumes day="1" if not specified for the 
	 purpose of calculating the expiry date).  With drafts it is normally sufficient to 
	 specify just the year. -->

    <!-- Meta-data Declarations -->

    <area>Internet</area>

    <workgroup>Light-Weight Implementation Guidance</workgroup>

    <!-- WG name at the upperleft corner of the doc,
         IETF is fine for individual submissions.  
	 If this element is not present, the default is "Network Working Group",
         which is used by the RFC Editor as a nod to the history of the IETF. -->

    <keyword>template</keyword>

    <!-- Keywords will be incorporated into HTML output
         files in a meta tag but they have no effect on text or nroff
         output. If you submit your draft to the RFC Editor, the
         keywords will be used for the search engine. -->

    <abstract>
      <t>The Constrained Application Protocol (CoAP) is designed for
      resource-constrained nodes and networks, e.g., sensor nodes in low-power
      lossy networks (LLNs). Still, to implement this Internet protocol on
      Class 1 devices, i.e., ~10KiB of RAM and ~100KiB of ROM, light-weight
      implementation techniques are necessary. This document provides the
      lessons learned from implementing CoAP for Contiki, an operating system
      for tiny, battery-operated networked embedded systems. The information
      may become part of the Light-Weight Implementation Guidance document
      planned by the IETF working group LWIG.</t>
    </abstract>
  </front>

  <middle>
    <section title="Introduction">
      <t>The Internet protocol suite is a suitable solution to realize an
      Internet of Things (IoT), a network of tiny networked embedded devices
      that create a link to the physical world. The narrow waist of IP can be
      used to directly access sensor readings throughout a sustainable city,
      acquire the necessary information for the smart grid, or control smart
      homes, buildings, and factories---seamlessly from the existing IT
      infrastructure. The layered architecture helps to manage the complexity,
      as multiple aspects such as routing over lossy links, link layer
      adaption, and low-power communication have to be addressed. Nonetheless,
      attention has to be given to achieve light-weight implementations that
      can run on resource-constrained devices such as sensor nodes with only
      microcontroller units (MCUs), ~10KiB of RAM, and ~100KiB of ROM <xref
      target="I-D.ietf-lwig-guidance"/>. <xref target="fig_stack"/> depicts a
      typical stack configuration for such Class 1 devices. This document
      discusses a light-weight implementation of CoAP at the application layer
      in <xref target="sec_coap"/> and techniques for energy-efficiency such
      as radio duty cycling in <xref target="sec_lowpower"/>.</t>

      <figure align="center" anchor="fig_stack">
        <preamble/>

        <artwork align="center"><![CDATA[+--------------------+--------------------------+
| Layer              | Protocol                 |
+--------------------+--------------------------+
| Application        | CoAP                     |
| Transport          | UDP                      |
| Network            | IPv6 / RPL               |
| Adaptation         | 6LoWPAN                  |
| MAC                | CSMA / link-layer bursts |
| Radio Duty Cycling | ContikiMAC               |
| Physical           | IEEE 802.15.4            |
+--------------------+--------------------------+]]></artwork>

        <postamble>A typical stack configuration for Class 1
        devices.</postamble>
      </figure>
    </section>

    <section anchor="sec_coap" title="Implementing CoAP">
      <t>The following experience stems from implementing CoAP for the Contiki
      operating system <xref target="ERBIUM"/>, but is generalized for any
      embedded OS. The information is not meant to be a final solution, but a
      first step towards a Light-Weight Implementation Guidance contribution.
      Alternatives will be incorporated throughout the merging process. The
      document assumes detailed knowledge of CoAP, its message format and
      interaction model. For more information, please refer to to <xref
      target="I-D.ietf-core-coap"/>, <xref target="I-D.ietf-core-block"/>, and
      <xref target="I-D.ietf-core-observe"/>.</t>

      <section title="Memory Management">
        <t>For embedded systems, it is common practice to allocate memory
        statically to ensure stable behavior, as no memory management unit
        (MMU) or other abstractions are available. For a CoAP node, the two
        key parameters are the number of (re)transmission buffers and the
        maximum message size that must be supported by each buffer. It is
        common practice to set the maximum message size far below the
        1280-byte MTU of 6LoWPAN to allow more than one open confirmable
        transmissions at a time (in particular for observe notifications).
        Note that implementations on constrained platforms often not even
        support the full MTU. Larger messages must then use blockwise
        transfers <xref target="I-D.ietf-core-block"/>, while a good trade-off
        between 6LoWPAN fragmentation and CoAP header overhead must be found.
        Usually the amount of available free RAM dominates this decision, on
        current platforms ending up at a maximum message size of 128 or 256
        bytes plus maximum estimated header size.</t>
      </section>

      <section title="Message Buffers">
        <t>Class 1 devices usually run an OS or event loop system with
        cooperative multi-threading. This allows to optimize memory usage
        through in-place processing and reuse of buffers. Incoming payload and
        byte strings of the header can be directly accessed in the IP buffer,
        which is provided by the OS, using pointers. For numeric options,
        there are two alternatives: Either process the header on the fly when
        an option is accessed or initially parse/allocate all values into a
        local data structure. Although the latter choice requires an
        additional amount of memory, it is preferable. First, local processing
        anyway requires integers in host byte order and stored in a variable
        of corresponding type. Second, on-the-fly processing might force
        developers to set options for outgoing messages in a specific order or
        cause extensive memmove operations due to CoAP's delta encoding.</t>

        <t>CoAP servers can significantly benefit from in-place processing, as
        they can create responses directly in the incoming IP buffer. When a
        CoAP server only sends piggy-backed or non-confirmable responses, no
        additional buffer is required in the application layer. This, however,
        requires an elaborated timing so that no incoming data is overwritten
        before it was processed. Note that an embedded OS usually reuses a
        single buffer for incoming and outgoing IP packets. So, either care or
        a buffer to save the incoming data has to be spent in any case.</t>

        <t>For clients, this is only an option for non-reliable requests that
        do not need to be kept for retransmission. Using the IP also for
        retransmissions would require to forbid any packet reception during an
        open request, but could be applied in some cases.</t>

        <t>Empty ACKs and RST messages can promptly be assembled and sent
        using the IP buffer. The first few bytes are usually parsed into the
        local data structure and can be overwritten without harm.</t>
      </section>

      <section title="Retransmissions">
        <t>CoAP's reliable transmissions require the before-mentioned
        retransmission buffers. For clients, obviously the request has to be
        stored, preferably already serialized. For servers, retransmissions
        apply for confirmable separate responses and confirmable notifications
        <xref target="I-D.ietf-core-observe"/>. As separate responses stem
        from long-lasting resource handlers, the response should be stored for
        retransmission instead of re-dispatching a stored request (which would
        allow for updating the representation). For confirmable notifications,
        please see <xref target="sec_observe"/>, as simply storing the
        response can break the concept of eventual consistency.</t>

        <t>String payloads such as JSON require a buffer to print to. By
        splitting the retransmission buffer into header and payload part, it
        can be reused. First to generate the payload and then storing the CoAP
        message by serializing into the same memory. Thus, providing a
        retransmission for any message type can save the need for a separate
        application buffer. This, however, requires an estimation about the
        maximum expected header size to split the buffer and a memmove to
        concatenate the two parts.</t>
      </section>

      <section title="Separate Responses">
        <t>Separate responses are required for long-lasting resource handlers
        that are too expensive to continuously update in the background to
        instantly answer from a fresh cache. If possible, those handlers
        should be realized with split phase execution (e.g., enable a slow
        sensor, return, and wait for a callback) to not fully block the server
        during that time. A convenient mechanism to store required data such
        as the client address and to automatically send the empty ACK could be
        provided by the implementation. This avoids code duplication when the
        server has multiple separate resource handlers.</t>
      </section>

      <section title="Deduplication">
        <t>Deduplication is heavy for Class 1 devices, as the number of peer
        addresses can be vast. Servers should be kept stateless, i.e., the
        REST API should be designed idempotent whenever possible. When this is
        not the case, the resource handler could perform an optimized
        deduplication by exploiting knowledge about the application. Another,
        server-wide strategy is to only keep track of non-idempotent
        requests.</t>
      </section>

      <section anchor="sec_observe" title="Observing">
        <t>At the server, the list of observers should be stored per resource
        to only have a handle per observable resource in a superordinate list
        instead of one resource handle per observer entry. Then for each
        observer, at least address, port, token, and the last outgoing message
        ID has to be stored. The latter is needed to match incoming RST
        messages and cancel the observe relationship.</t>

        <t>Besides the list of observers, it is best to have one
        retransmission buffer per observable resource. Each notification is
        serialized once into this buffer and only address, port, and token are
        changed when iterating over the observer list (note that different
        token lengths might require realignment). The advantage becomes clear
        for confirmable notifications: Instead of one retransmission buffer
        per observer, only one buffer and only individual retransmission
        counters and timers in the list entry need to be stored. When the
        notifications can be sent fast enough, even a single timer would
        suffice. Furthermore, per-resource buffers simplify the update with a
        new resource state during open deliveries.</t>
      </section>

      <section title="Blockwise Transfers">
        <t>Blockwise transfers have the main purpose of providing
        fragmentation at the application layer, where partial information can
        be processed. This is not possible at lower layers such as 6LoWPAN, as
        only assembled packets can be passed up the stack. While <xref
        target="I-D.ietf-core-block"/> also anticipates atomic handling of
        blocks, i.e., only fully received CoAP messages, this is not possible
        on Class 1 devices.</t>

        <t>When receiving a blockwise transfer, each blocks is usually passed
        to a handler function that for instance performs stream processing or
        writes the blocks to external memory such as flash. Although there are
        no restrictions in <xref target="I-D.ietf-core-block"/>, it is
        beneficial for Class 1 devices to only allow ordered transmission of
        blocks. Otherwise on-the-fly processing would not be possible.</t>

        <t>When sending a blockwise transfer, Class 1 devices usually do not
        have sufficient memory to print the full message into a buffer, and
        slice and send it in a second step. When transferring the CoRE Link
        Format from /.well-known/core for instance, a generator function is
        required that generates slices of a large string with a specific
        offset length (a 'sonprintf()'). This functionality is required
        recurrently and should be included in a library.</t>
      </section>

      <section title="Developer API">
        <t>Bringing a Web transfer protocol to constrained environments does
        not only change the networking of the corresponding systems, but also
        the way they should be programmed. A CoAP implementation should
        provide a developer API similar to REST frameworks in traditional
        computing. A server should not be created around an event loop with
        several function calls, but rather by implementing handlers following
        the resource abstraction.</t>

        <t>So far, the following types of RESTful resources were
        identified:<list style="hanging">
            <t hangText="NORMAL">A normal resource defined by a static
            Uri-Path that is associated with a resource handler function.
            Allowed methods could already be filtered by the implementation
            based on flags. This is the basis for all other resource
            types.</t>

            <t hangText="PARENT">A parent resource manages several
            sub-resources by programmatically evaluating the Uri-Path, which
            may be longer than that of the parent resource. Defining a URI
            templates (see <xref target="RFC6570"/>) would be a convenient way
            to pre-parse arguments given in the Uri-Path.</t>

            <t hangText="PERIODIC">A resource that has an additional handler
            function that is triggered periodically by the CoAP implementation
            with a resource-defined interval. It can be used to sample a
            sensor or perform similar periodic updates. Usually, a periodic
            resource is observable and sends the notifications in the periodic
            handler function. These periodic tasks are quite common for sensor
            nodes, thus it makes sense to provide this functionality in the
            CoAP implementation and avoid redundant code in every
            resource.</t>

            <t hangText="EVENT">An event resource is similar to an periodic
            resource, only that the second handler is called by an irregular
            event such as a button.</t>
          </list></t>
      </section>
    </section>

    <section anchor="sec_lowpower" title="Low-power Wireless">
      <t>The Internet of wireless things needs power-efficient protocols, but
      existing protocols have typically been designed without explicit
      power-efficiency. CoAP is optimized to run over low-power link layers
      such IEEE 802.15.4, but in low-power wireless systems, ultimate
      power-efficiency translates into the ability to keep the radio off as
      much as possible, as the radio transceiver is typically the most
      power-consuming component. This can be achieved in two ways: So called
      radio duty cycling (RDC) aims to keep the radio off as much as possible,
      but performs periodic channel checks to realize a virtual always-on
      link. Sleepy nodes instead put the radio into hibernation for a long
      period during which the node is fully disconnected from the network.</t>

      <section title="Radio Duty Cycling">
        <t>RDC can be achieved through a separate, independent layer between
        PHY and MAC as depicted in <xref target="fig_stack"/>. The upper
        layers can remain more or less untouched and only experience a higher
        latency, which might require tweaking the timeout parameters.
        State-of-the-art RDC layers can achieve an idle duty cycling way below
        1% while checking the channel several times per second. ContikiMAC for
        instance achieves a 0.3% cycle with a channel check rate of 4 Hz,
        which results in a worst-case delay of 250ms per hop. While saving
        energy, ContikiMAC also makes link-layer transmissions more robust due
        to its retransmission policy. Please refer to <xref target="CONMAC"/>
        for details.</t>

        <t>In general, RDC can be divided into two approaches: sender
        initiated (e.g., ContikiMAC) and receiver initiated (e.g., A-MAC <xref
        target="AMAC"/>). In the first approach, the sender enables the radio
        first and continuously transmits its message in a strobe until a
        link-layer ACK is received (note that for IEEE 802.15.4 transceivers,
        transmitting consumes less energy than receiving). Receivers turn on
        their radio only periodically to check for these announcements. If
        they sense a busy channel, the radio is kept on to receive a potential
        message and finally acknowledge it. In the other approach, the
        receiver periodically announces that it will keep the radio on for
        receiving for a while. The senders turns on its radio and listens for
        an announcement of the recipient. When that is received, it transmits
        the message (following the scheme of the above MAC layer of course,
        while back-offs must match the awake time after announcements). Which
        approach is optimal mainly depends on the communication pattern of the
        application. Sender initiated RDCs are more efficient for IEEE
        802.15.4, but the strobes can congest a busy channel.</t>
      </section>

      <section title="Sleepy Nodes">
        <t>Going to sleep for a longer time is not transparent for the
        application layer, as nodes need to re-synchronize and maybe
        re-associate with the network. Several drafts in the IETF CoRE working
        group cover this strategy for low-power wireless networking (cf. <xref
        target="I-D.vial-core-mirror-proxy"/>, <xref
        target="I-D.fossati-core-publish-option"/>, <xref
        target="I-D.fossati-core-monitor-option"/>, and <xref
        target="I-D.rahman-core-sleepy"/>). Such features will have to be
        integrated into the nodes CoAP implementation as well as the back-end
        systems. In addition, alternatives to standard diagnosis tools such as
        ICMP ping will have to be provided, e.g., heartbeats by the
        application.</t>

        <t>This strategy is particular useful for communications other than
        IEEE 802.15.4. Low-power Wi-Fi for instance is mainly based on long
        sleeping periods with short wake-up cycles. Although the data rate
        would be high enough for HTTP over TCP, low-power Wi-FI can greatly
        benefit from CoAP and its shorter round trip times. For further
        information about sleepy nodes based on low-power Wi-Fi see <xref
        target="LPWIFI"/>.</t>
      </section>
    </section>

    <!-- This PI places the pagebreak correctly (before the section title) in the text output. -->

    <!-- Possibly a 'Contributors' section ... -->

    <section anchor="Security" title="Security Considerations">
      <t>T.B.D.</t>
    </section>
  </middle>

  <!--  *****BACK MATTER ***** -->

  <back>
    <!-- References split into informative and normative -->

    <!-- There are 2 ways to insert reference entries from the citation libraries:
     1. define an ENTITY at the top, and use "ampersand character"RFC2629; here (as shown)
     2. simply use a PI "less than character"?rfc include="reference.RFC.2119.xml"?> here
        (for I-Ds: include="reference.I-D.narten-iana-considerations-rfc2434bis.xml")

     Both are cited textually in the same manner: by using xref elements.
     If you use the PI option, xml2rfc will, by default, try to find included files in the same
     directory as the including file. You can also define the XML_LIBRARY environment variable
    with a value containing a set of directories to search.  These can be either in the local
     filing system or remote ones accessed by http (http://domain/dir/... ).-->

    <references title="Informative References">
      <!-- Here we use entities that we defined at the beginning. -->

      &I-D.ietf-lwig-guidance;

      &I-D.ietf-core-coap;

      &I-D.ietf-core-block;

      &I-D.ietf-core-observe;

      &I-D.vial-core-mirror-proxy;

      &I-D.fossati-core-publish-option;

      &I-D.fossati-core-monitor-option;

      &I-D.rahman-core-sleepy;

      &RFC6550;

      &RFC6570;

      <!-- A reference written by by an organization not a person. -->

      <reference anchor="ERBIUM">
        <front>
          <title>A Low-Power CoAP for Contiki</title>

          <author fullname="Matthias Kovatsch" initials="M."
                  surname="Kovatsch"/>

          <author fullname="Simon Duquennoy" initials="S." surname="Duquennoy"/>

          <author fullname="Adam Dunkels" initials="A." surname="Dunkels"/>

          <date month="October" year="2011"/>
        </front>

        <seriesInfo name="In"
                    value="Proceedings of the 8th IEEE International Conference on Mobile Ad-hoc and Sensor Systems (MASS 2011). Valencia, Spain"/>
      </reference>

      <reference anchor="CONMAC">
        <front>
          <title>The ContikiMAC Radio Duty Cycling Protocol</title>

          <author fullname="Adam Dunkels" initials="A." surname="Dunkels"/>

          <date month="December" year="2011"/>
        </front>

        <seriesInfo name="SICS Technical Report" value="T2011:13"/>

        <seriesInfo name="ISSN" value="1100-3154"/>
      </reference>

      <reference anchor="AMAC">
        <front>
          <title>Designand Evaluation of a Versatile and Efficient
          Receiver-Initiated Link Layer for Low-Power Wireless</title>

          <author fullname="Prabal Dutta" initials="P." surname="Dutta"/>

          <author fullname="Stephen Dawson-Haggerty" initials="S."
                  surname="Dawson-Haggerty"/>

          <author fullname="Yin Chen" initials="A." surname="Y."/>

          <author fullname="Chieh-Jan Mike Liang" initials="C.-J. M."
                  surname="Liang"/>

          <author fullname="Andreas Terzis" initials="A." surname="Terzis"/>

          <date month="November" year="2010"/>
        </front>

        <seriesInfo name="In"
                    value="Proceedings of the International Conference on Embedded Networked Sensor Systems (SenSys 2010). Zurich, Switzerland"/>
      </reference>

      <reference anchor="LPWIFI">
        <front>
          <title>Connecting Things to the Web using Programmable Low-power
          WiFi Modules</title>

          <author fullname="Benedikt Ostermaier" initials="B."
                  surname="Ostermaier"/>

          <author fullname="Matthias Kovatsch" initials="M."
                  surname="Kovatsch"/>

          <author fullname="Silvia Santini" initials="S." surname="Santini"/>

          <date month="June" year="2011"/>
        </front>

        <seriesInfo name="In"
                    value="Proceedings of the 2nd International Workshop on the Web of Things (WoT 2011). San Francisco, CA, USA"/>
      </reference>
    </references>

    <!-- Change Log

v00 2006-03-15  EBD   Initial version

v01 2006-04-03  EBD   Moved PI location back to position 1 -
                      v3.1 of XMLmind is better with them at this location.
v02 2007-03-07  AH    removed extraneous nested_list attribute,
                      other minor corrections
v03 2007-03-09  EBD   Added comments on null IANA sections and fixed heading capitalization.
                      Modified comments around figure to reflect non-implementation of
                      figure indent control.  Put in reference using anchor="DOMINATION".
                      Fixed up the date specification comments to reflect current truth.
v04 2007-03-09 AH     Major changes: shortened discussion of PIs,
                      added discussion of rfc include.
v05 2007-03-10 EBD    Added preamble to C program example to tell about ABNF and alternative 
                      images. Removed meta-characters from comments (causes problems).  -->
  </back>
</rfc>

PAFTECH AB 2003-20262026-04-23 10:14:56