# public fanakin /contiki-mirror forked from contiki/contiki-mirror

### Subversion checkout URL

You can clone with HTTPS or Subversion.

Fetching contributors…

Cannot retrieve contributors at this time

file 1193 lines (986 sloc) 50.833 kb
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 /**\addtogroup net@{*//**\defgroup uip The uIP TCP/IP stack@{The uIP TCP/IP stack provides Internet communication abilities toContiki.\section uip-introduction uIP introductionThe uIP TCP/IP stack is intended to make it possible to communicateusing the TCP/IP protocol suite even on small 8-bitmicro-controllers. Despite being small and simple, uIP do not requiretheir peers to have complex, full-size stacks, but can communicatewith peers running a similarly light-weight stack. The code size is onthe order of a few kilobytes and RAM usage can be configured to be aslow as a few hundred bytes.uIP can be found at the uIP web page: http://www.sics.se/~adam/uip/\sa \ref tcpip \sa \ref uip6 and sicslowpan\sa \ref uipopt "uIP Compile-time configuration options"\sa \ref uipconffunc "uIP Run-time configuration functions"\sa \ref uipinit "uIP initialization functions"\sa \ref uipdevfunc "uIP device driver interface" and    \ref uipdrivervars "uIP variables used by device drivers"\sa \ref uipappfunc "uIP functions called from application programs"(see below) and the \ref psock "protosockets API" and their underlying\ref pt "protothreads" \section uIPIntroduction IntroductionWith the success of the Internet, the TCP/IP protocol suite has becomea global standard for communication. TCP/IP is the underlying protocolused for web page transfers, e-mail transmissions, file transfers, andpeer-to-peer networking over the Internet. For embedded systems, beingable to run native TCP/IP makes it possible to connect the systemdirectly to an intranet or even the global Internet. Embedded deviceswith full TCP/IP support will be first-class network citizens, thusbeing able to fully communicate with other hosts in the network.Traditional TCP/IP implementations have required far too muchresources both in terms of code size and memory usage to be useful insmall 8 or 16-bit systems. Code size of a few hundred kilobytes andRAM requirements of several hundreds of kilobytes have made itimpossible to fit the full TCP/IP stack into systems with a few tensof kilobytes of RAM and room for less than 100 kilobytes ofcode.The uIP implementation is designed to have only the absolute minimalset of features needed for a full TCP/IP stack. It can only handle asingle network interface and contains the IP, ICMP, UDP and TCPprotocols. uIP is written in the C programming language.Many other TCP/IP implementations for small systems assume that theembedded device always will communicate with a full-scale TCP/IPimplementation running on a workstation-class machine. Under thisassumption, it is possible to remove certain TCP/IP mechanisms thatare very rarely used in such situations. Many of those mechanisms areessential, however, if the embedded device is to communicate withanother equally limited device, e.g., when running distributedpeer-to-peer services and protocols. uIP is designed to be RFCcompliant in order to let the embedded devices to act as first-classnetwork citizens. The uIP TCP/IP implementation that is not tailoredfor any specific application.\section uip-tcpip TCP/IP CommunicationThe full TCP/IP suite consists of numerous protocols, ranging from lowlevel protocols such as ARP which translates IP addresses to MACaddresses, to application level protocols such as SMTP that is used totransfer e-mail. The uIP is mostly concerned with the TCP and IPprotocols and upper layer protocols will be referred to as "theapplication". Lower layer protocols are often implemented in hardwareor firmware and will be referred to as "the network device" that arecontrolled by the network device driver.TCP provides a reliable byte stream to the upper layer protocols. Itbreaks the byte stream into appropriately sized segments and eachsegment is sent in its own IP packet. The IP packets are sent out onthe network by the network device driver. If the destination is not onthe physically connected network, the IP packet is forwarded ontoanother network by a router that is situated between the twonetworks. If the maximum packet size of the other network is smallerthan the size of the IP packet, the packet is fragmented into smallerpackets by the router. If possible, the size of the TCP segments arechosen so that fragmentation is minimized. The final recipient of thepacket will have to reassemble any fragmented IP packets before theycan be passed to higher layers.The formal requirements for the protocols in the TCP/IP stack isspecified in a number of RFC documents published by the InternetEngineering Task Force, IETF. Each of the protocols in the stack isdefined in one more RFC documents and RFC1122 collectsall requirements and updates the previous RFCs. The RFC1122 requirements can be divided into two categories; thosethat deal with the host to host communication and those that deal withcommunication between the application and the networking stack. Anexample of the first kind is "A TCP MUST be able to receive a TCPoption in any segment" and an example of the second kind is "ThereMUST be a mechanism for reporting soft TCP error conditions to theapplication." A TCP/IP implementation that violates requirements ofthe first kind may not be able to communicate with other TCP/IPimplementations and may even lead to network failures. Violation ofthe second kind of requirements will only affect the communicationwithin the system and will not affect host-to-host communication.In uIP, all RFC requirements that affect host-to-host communicationare implemented. However, in order to reduce code size, we haveremoved certain mechanisms in the interface between the applicationand the stack, such as the soft error reporting mechanism anddynamically configurable type-of-service bits for TCPconnections. Since there are only very few applications that make useof those features they can be removed without loss of generality.\section mainloop Main Control LoopThe uIP stack can be run either as a task in a multitasking system, oras the main program in a singletasking system. In both cases, the maincontrol loop does two things repeatedly: - Check if a packet has arrived from the network. - Check if a periodic timeout has occurred.If a packet has arrived, the input handler function, uip_input(),should be invoked by the main control loop. The input handler functionwill never block, but will return at once. When it returns, the stackor the application for which the incoming packet was intended may haveproduced one or more reply packets which should be sent out. If so,the network device driver should be called to send out these packets.Periodic timeouts are used to drive TCP mechanisms that depend ontimers, such as delayed acknowledgments, retransmissions andround-trip time estimations. When the main control loop infers thatthe periodic timer should fire, it should invoke the timer handlerfunction uip_periodic(). Because the TCP/IP stack may performretransmissions when dealing with a timer event, the network devicedriver should called to send out the packets that may have been produced.\section arch Architecture Specific FunctionsuIP requires a few functions to be implemented specifically for thearchitecture on which uIP is intended to run. These functions shouldbe hand-tuned for the particular architecture, but generic Cimplementations are given as part of the uIP distribution.\subsection checksums Checksum CalculationThe TCP and IP protocols implement a checksum that covers the data andheader portions of the TCP and IP packets. Since the calculation ofthis checksum is made over all bytes in every packet being sent andreceived it is important that the function that calculates thechecksum is efficient. Most often, this means that the checksumcalculation must be fine-tuned for the particular architecture onwhich the uIP stack runs.While uIP includes a generic checksum function, it also leaves it openfor an architecture specific implementation of the two functionsuip_ipchksum() and uip_tcpchksum(). The checksum calculations in thosefunctions can be written in highly optimized assembler rather thangeneric C code.\subsection longarith 32-bit ArithmeticThe TCP protocol uses 32-bit sequence numbers, and a TCPimplementation will have to do a number of 32-bit additions as part ofthe normal protocol processing. Since 32-bit arithmetic is notnatively available on many of the platforms for which uIP is intended,uIP leaves the 32-bit additions to be implemented by the architecturespecific module and does not make use of any 32-bit arithmetic in themain code base.While uIP implements a generic 32-bit addition, there is support forhaving an architecture specific implementation of the uip_add32()function.\section memory Memory ManagementIn the architectures for which uIP is intended, RAM is the mostscarce resource. With only a few kilobytes of RAM available for theTCP/IP stack to use, mechanisms used in traditional TCP/IP cannot bedirectly applied.The uIP stack does not use explicit dynamic memoryallocation. Instead, it uses a single global buffer for holdingpackets and has a fixed table for holding connection state. The globalpacket buffer is large enough to contain one packet of maximumsize. When a packet arrives from the network, the device driver placesit in the global buffer and calls the TCP/IP stack. If the packetcontains data, the TCP/IP stack will notify the correspondingapplication. Because the data in the buffer will be overwritten by thenext incoming packet, the application will either have to actimmediately on the data or copy the data into a secondary buffer forlater processing. The packet buffer will not be overwritten by newpackets before the application has processed the data. Packets thatarrive when the application is processing the data must be queued,either by the network device or by the device driver. Most single-chipEthernet controllers have on-chip buffers that are large enough tocontain at least 4 maximum sized Ethernet frames. Devices that arehandled by the processor, such as RS-232 ports, can copy incomingbytes to a separate buffer during application processing. If thebuffers are full, the incoming packet is dropped. This will causeperformance degradation, but only when multiple connections arerunning in parallel. This is because uIP advertises a very smallreceiver window, which means that only a single TCP segment will be inthe network per connection.In uIP, the same global packet buffer that is used for incomingpackets is also used for the TCP/IP headers of outgoing data. If theapplication sends dynamic data, it may use the parts of the globalpacket buffer that are not used for headers as a temporary storagebuffer. To send the data, the application passes a pointer to the dataas well as the length of the data to the stack. The TCP/IP headers arewritten into the global buffer and once the headers have beenproduced, the device driver sends the headers and the application dataout on the network. The data is not queued forretransmissions. Instead, the application will have to reproduce thedata if a retransmission is necessary.The total amount of memory usage for uIP depends heavily on theapplications of the particular device in which the implementations areto be run. The memory configuration determines both the amount oftraffic the system should be able to handle and the maximum amount ofsimultaneous connections. A device that will be sending large e-mailswhile at the same time running a web server with highly dynamic webpages and multiple simultaneous clients, will require more RAM than asimple Telnet server. It is possible to run the uIP implementationwith as little as 200 bytes of RAM, but such a configuration willprovide extremely low throughput and will only allow a small number ofsimultaneous connections.\section api Application Program Interface (API)The Application Program Interface (API) defines the way theapplication program interacts with the TCP/IP stack. The most commonlyused API for TCP/IP is the BSD socket API which is used in most Unixsystems and has heavily influenced the Microsoft Windows WinSockAPI. Because the socket API uses stop-and-wait semantics, it requiressupport from an underlying multitasking operating system. Since theoverhead of task management, context switching and allocation of stackspace for the tasks might be too high in the intended uIP targetarchitectures, the BSD socket interface is not suitable for ourpurposes.uIP provides two APIs to programmers: protosockets, a BSD socket-likeAPI without the overhead of full multi-threading, and a "raw"event-based API that is nore low-level than protosockets but uses lessmemory.\sa \ref psock\sa \ref pt\subsection rawapi The uIP raw APIThe "raw" uIP API uses an event driven interface where the application isinvoked in response to certain events. An application running on topof uIP is implemented as a C function that is called by uIP inresponse to certain events. uIP calls the application when data isreceived, when data has been successfully delivered to the other endof the connection, when a new connection has been set up, or when datahas to be retransmitted. The application is also periodically polledfor new data. The application program provides only one callbackfunction; it is up to the application to deal with mapping differentnetwork services to different ports and connections. Because theapplication is able to act on incoming data and connection requests assoon as the TCP/IP stack receives the packet, low response times canbe achieved even in low-end systems.uIP is different from other TCP/IP stacks in that it requires helpfrom the application when doing retransmissions. Other TCP/IP stacksbuffer the transmitted data in memory until the data is known to besuccessfully delivered to the remote end of the connection. If thedata needs to be retransmitted, the stack takes care of theretransmission without notifying the application. With this approach,the data has to be buffered in memory while waiting for anacknowledgment even if the application might be able to quicklyregenerate the data if a retransmission has to be made.In order to reduce memory usage, uIP utilizes the fact that theapplication may be able to regenerate sent data and lets theapplication take part in retransmissions. uIP does not keep track ofpacket contents after they have been sent by the device driver, anduIP requires that the application takes an active part in performingthe retransmission. When uIP decides that a segment should beretransmitted, it calls the application with a flag set indicatingthat a retransmission is required. The application checks theretransmission flag and produces the same data that was previouslysent. From the application's standpoint, performing a retransmissionis not different from how the data originally was sent. Therefore theapplication can be written in such a way that the same code is usedboth for sending data and retransmitting data. Also, it is importantto note that even though the actual retransmission operation iscarried out by the application, it is the responsibility of the stackto know when the retransmission should be made. Thus the complexity ofthe application does not necessarily increase because it takes anactive part in doing retransmissions.\subsubsection appevents Application EventsThe application must be implemented as a C function, UIP_APPCALL(),that uIP calls whenever an event occurs. Each event has a correspondingtest function that is used to distinguish between differentevents. The functions are implemented as C macros that will evaluateto either zero or non-zero. Note that certain events can happen inconjunction with each other (i.e., new data can arrive at the sametime as data is acknowledged).\subsubsection connstate The Connection PointerWhen the application is called by uIP, the global variable uip_conn isset to point to the uip_conn structure for the connection thatcurrently is handled, and is called the "current connection". Thefields in the uip_conn structure for the current connection can beused, e.g., to distinguish between different services, or to check towhich IP address the connection is connected. One typical use would beto inspect the uip_conn->lport (the local TCP port number) to decidewhich service the connection should provide. For instance, anapplication might decide to act as an HTTP server if the value ofuip_conn->lport is equal to 80 and act as a TELNET server if the valueis 23. \subsubsection recvdata Receiving DataIf the uIP test function uip_newdata() is non-zero, the remote host ofthe connection has sent new data. The uip_appdata pointer point to theactual data. The size of the data is obtained through the uIP functionuip_datalen(). The data is not buffered by uIP, but will beoverwritten after the application function returns, and theapplication will therefor have to either act directly on the incomingdata, or by itself copy the incoming data into a buffer for laterprocessing.\subsubsection senddata Sending DataWhen sending data, uIP adjusts the length of the data sent by theapplication according to the available buffer space and the currentTCP window advertised by the receiver. The amount of buffer space isdictated by the memory configuration. It is therefore possible thatall data sent from the application does not arrive at the receiver,and the application may use the uip_mss() function to see how muchdata that actually will be sent by the stack.The application sends data by using the uIP function uip_send(). Theuip_send() function takes two arguments; a pointer to the data to besent and the length of the data. If the application needs RAM spacefor producing the actual data that should be sent, the packet buffer(pointed to by the uip_appdata pointer) can be used for this purpose.The application can send only one chunk of data at a time on aconnection and it is not possible to call uip_send() more than onceper application invocation; only the data from the last call will besent.\subsubsection rexmitdata Retransmitting DataRetransmissions are driven by the periodic TCP timer. Every time theperiodic timer is invoked, the retransmission timer for eachconnection is decremented. If the timer reaches zero, a retransmissionshould be made. As uIP does not keep track of packet contents after they havebeen sent by the device driver, uIP requires that theapplication takes an active part in performing theretransmission. When uIP decides that a segment should beretransmitted, the application function is called with theuip_rexmit() flag set, indicating that a retransmission isrequired.The application must check the uip_rexmit() flag and produce the samedata that was previously sent. From the application's standpoint,performing a retransmission is not different from how the dataoriginally was sent. Therefor, the application can be written in sucha way that the same code is used both for sending data andretransmitting data. Also, it is important to note that even thoughthe actual retransmission operation is carried out by the application,it is the responsibility of the stack to know when the retransmissionshould be made. Thus the complexity of the application does notnecessarily increase because it takes an active part in doingretransmissions.\subsubsection closing Closing ConnectionsThe application closes the current connection by calling theuip_close() during an application call. This will cause the connectionto be cleanly closed. In order to indicate a fatal error, theapplication might want to abort the connection and does so by callingthe uip_abort() function.If the connection has been closed by the remote end, the test functionuip_closed() is true. The application may then do any necessarycleanups.\subsubsection errors Reporting ErrorsThere are two fatal errors that can happen to a connection, eitherthat the connection was aborted by the remote host, or that theconnection retransmitted the last data too many times and has beenaborted. uIP reports this by calling the application function. Theapplication can use the two test functions uip_aborted() anduip_timedout() to test for those error conditions.\subsubsection polling PollingWhen a connection is idle, uIP polls the application every time theperiodic timer fires. The application uses the test functionuip_poll() to check if it is being polled by uIP.The polling event has two purposes. The first is to let theapplication periodically know that a connection is idle, which allowsthe application to close connections that have been idle for toolong. The other purpose is to let the application send new data thathas been produced. The application can only send data when invoked byuIP, and therefore the poll event is the only way to send data on anotherwise idle connection.\subsubsection listen Listening PortsuIP maintains a list of listening TCP ports. A new port is opened forlistening with the uip_listen() function. When a connection requestarrives on a listening port, uIP creates a new connection and callsthe application function. The test function uip_connected() is true ifthe application was invoked because a new connection was created.The application can check the lport field in the uip_conn structure tocheck to which port the new connection was connected.\subsubsection connect Opening ConnectionsNew connections can be opened from withinuIP by the function uip_connect(). This functionallocates a new connection and sets a flag in the connection statewhich will open a TCP connection to the specified IP address and portthe next time the connection is polled by uIP. The uip_connect()function returnsa pointer to the uip_conn structure for the newconnection. If there are no free connection slots, the functionreturns NULL. The function uip_ipaddr() may be used to pack an IP address into thetwo element 16-bit array used by uIP to represent IP addresses.Two examples of usage are shown below. The first example shows how toopen a connection to TCP port 8080 of the remote end of the currentconnection. If there are not enough TCP connection slots to allow anew connection to be opened, the uip_connect() function returns NULLand the current connection is aborted by uip_abort(). \codevoid connect_example1_app(void) {   if(uip_connect(uip_conn->ripaddr, HTONS(8080)) == NULL) {      uip_abort();   }} \endcodeThe second example shows how to open a new connection to a specific IPaddress. No error checks are made in this example.\codevoid connect_example2(void) {   uip_addr_t ipaddr;   uip_ipaddr(ipaddr, 192,168,0,1);   uip_connect(ipaddr, HTONS(8080));}\endcode\section examples ExamplesThis section presents a number of very simple uIP applications. TheuIP code distribution contains several more complex applications.\subsection example1 A Very Simple ApplicationThis first example shows a very simple application. The applicationlistens for incoming connections on port 1234. When a connection hasbeen established, the application replies to all data sent to it bysaying "ok"The implementation of this application is shown below. The applicationis initialized with the function called example1_init() and the uIPcallback function is called example1_app(). For this application, theconfiguration variable UIP_APPCALL should be defined to beexample1_app().\codevoid example1_init(void) {   uip_listen(HTONS(1234));}void example1_app(void) {   if(uip_newdata() || uip_rexmit()) {      uip_send("ok\n", 3);   }}\endcodeThe initialization function calls the uIP function uip_listen() toregister a listening port. The actual application functionexample1_app() uses the test functions uip_newdata() and uip_rexmit()to determine why it was called. If the application was called becausethe remote end has sent it data, it responds with an "ok". If theapplication function was called because data was lost in the networkand has to be retransmitted, it also sends an "ok". Note that thisexample actually shows a complete uIP application. It is not requiredfor an application to deal with all types of events such asuip_connected() or uip_timedout(). \subsection example2 A More Advanced ApplicationThis second example is slightly more advanced than the previous one,and shows how the application state field in the uip_conn structure isused.This application is similar to the first application in that itlistens to a port for incoming connections and responds to data sentto it with a single "ok". The big difference is that this applicationprints out a welcoming "Welcome!" message when the connection has beenestablished.This seemingly small change of operation makes a big difference in howthe application is implemented. The reason for the increase incomplexity is that if data should be lost in the network, theapplication must know what data to retransmit. If the "Welcome!"message was lost, the application must retransmit the welcome and ifone of the "ok" messages is lost, the application must send a new"ok".The application knows that as long as the "Welcome!" message has notbeen acknowledged by the remote host, it might have been dropped inthe network. But once the remote host has sent an acknowledgmentback, the application can be sure that the welcome has been receivedand knows that any lost data must be an "ok" message. Thus theapplication can be in either of two states: either in the WELCOME-SENTstate where the "Welcome!" has been sent but not acknowledged, or inthe WELCOME-ACKED state where the "Welcome!" has been acknowledged.When a remote host connects to the application, the application sendsthe "Welcome!" message and sets it's state to WELCOME-SENT. When thewelcome message is acknowledged, the application moves to theWELCOME-ACKED state. If the application receives any new data from theremote host, it responds by sending an "ok" back.If the application is requested to retransmit the last message, itlooks at in which state the application is. If the application is inthe WELCOME-SENT state, it sends a "Welcome!" message since itknows that the previous welcome message hasn't been acknowledged. Ifthe application is in the WELCOME-ACKED state, it knows that the lastmessage was an "ok" message and sends such a message.The implementation of this application is seen below. Thisconfiguration settings for the application is follows after itsimplementation.\codestruct example2_state {   enum {WELCOME_SENT, WELCOME_ACKED} state;};void example2_init(void) {   uip_listen(HTONS(2345));}void example2_app(void) {   struct example2_state *s;   s = (struct example2_state *)uip_conn->appstate;      if(uip_connected()) {      s->state = WELCOME_SENT;      uip_send("Welcome!\n", 9);      return;   }    if(uip_acked() && s->state == WELCOME_SENT) {      s->state = WELCOME_ACKED;   }   if(uip_newdata()) {      uip_send("ok\n", 3);   }   if(uip_rexmit()) {      switch(s->state) {      case WELCOME_SENT:         uip_send("Welcome!\n", 9);         break;      case WELCOME_ACKED:         uip_send("ok\n", 3);         break;      }   }}\endcodeThe configuration for the application:\code#define UIP_APPCALL example2_app#define UIP_APPSTATE_SIZE sizeof(struct example2_state)\endcode\subsection example3 Differentiating Between ApplicationsIf the system should run multiple applications, one technique todifferentiate between them is to use the TCP port number of either theremote end or the local end of the connection. The example below showshow the two examples above can be combined into one application.\codevoid example3_init(void) {   example1_init();   example2_init(); }void example3_app(void) {   switch(uip_conn->lport) {   case HTONS(1234):      example1_app();      break;   case HTONS(2345):      example2_app();      break;   }}\endcode\subsection example4 Utilizing TCP Flow ControlThis example shows a simple application that connects to a host, sendsan HTTP request for a file and downloads it to a slow device such adisk drive. This shows how to use the flow control functions of uIP.\codevoid example4_init(void) {   uip_ipaddr_t ipaddr;   uip_ipaddr(ipaddr, 192,168,0,1);   uip_connect(ipaddr, HTONS(80));}void example4_app(void) {   if(uip_connected() || uip_rexmit()) {      uip_send("GET /file HTTP/1.0\r\nServer:192.186.0.1\r\n\r\n",               48);      return;   }   if(uip_newdata()) {      device_enqueue(uip_appdata, uip_datalen());      if(device_queue_full()) {         uip_stop();      }   }   if(uip_poll() && uip_stopped()) {      if(!device_queue_full()) {         uip_restart();      }   }}\endcodeWhen the connection has been established, an HTTP request is sent tothe server. Since this is the only data that is sent, the applicationknows that if it needs to retransmit any data, it is that request thatshould be retransmitted. It is therefore possible to combine these twoevents as is done in the example.When the application receives new data from the remote host, it sendsthis data to the device by using the function device_enqueue(). It isimportant to note that this example assumes that this function copiesthe data into its own buffers. The data in the uip_appdata buffer willbe overwritten by the next incoming packet.If the device's queue is full, the application stops the data from theremote host by calling the uIP function uip_stop(). The applicationcan then be sure that it will not receive any new data untiluip_restart() is called. The application polling event is used tocheck if the device's queue is no longer full and if so, the data flowis restarted with uip_restart().\subsection example5 A Simple Web ServerThis example shows a very simple file server application that listensto two ports and uses the port number to determine which file tosend. If the files are properly formatted, this simple application canbe used as a web server with static pages. The implementation follows.\codestruct example5_state {   char *dataptr;   unsigned int dataleft;};void example5_init(void) {   uip_listen(HTONS(80));   uip_listen(HTONS(81));}void example5_app(void) {   struct example5_state *s;   s = (struct example5_state)uip_conn->appstate;      if(uip_connected()) {      switch(uip_conn->lport) {      case HTONS(80):         s->dataptr = data_port_80;         s->dataleft = datalen_port_80;         break;      case HTONS(81):         s->dataptr = data_port_81;         s->dataleft = datalen_port_81;         break;      }      uip_send(s->dataptr, s->dataleft);      return;    }   if(uip_acked()) {      if(s->dataleft < uip_mss()) {         uip_close();         return;      }      s->dataptr += uip_conn->len;      s->dataleft -= uip_conn->len;      uip_send(s->dataptr, s->dataleft);    }}\endcodeThe application state consists of a pointer to the data that should besent and the size of the data that is left to send. When a remote hostconnects to the application, the local port number is used todetermine which file to send. The first chunk of data is sent usinguip_send(). uIP makes sure that no more than MSS bytes of data isactually sent, even though s->dataleft may be larger than the MSS. The application is driven by incoming acknowledgments. When data hasbeen acknowledged, new data can be sent. If there is no more data tosend, the connection is closed using uip_close().\subsection example6 Structured Application Program DesignWhen writing larger programs using uIP it is useful to be able toutilize the uIP API in a structured way. The following exampleprovides a structured design that has showed itself to be useful forwriting larger protocol implementations than the previous examplesshowed here. The program is divided into an uIP event handler functionthat calls seven application handler functions that process new data,act on acknowledged data, send new data, deal with connectionestablishment or closure events and handle errors. The functions arecalled newdata(), acked(), senddata(), connected(), closed(),aborted(), and timedout(), and needs to be written specifically forthe protocol that is being implemented.The uIP event handler function is shown below.\codevoid example6_app(void) {  if(uip_aborted()) {    aborted();  }  if(uip_timedout()) {    timedout();  }  if(uip_closed()) {    closed();  }  if(uip_connected()) {    connected();  }  if(uip_acked()) {    acked();  }  if(uip_newdata()) {    newdata();  }  if(uip_rexmit() ||     uip_newdata() ||     uip_acked() ||     uip_connected() ||     uip_poll()) {    senddata();  }}\endcodeThe function starts with dealing with any error conditions that mighthave happened by checking if uip_aborted() or uip_timedout() aretrue. If so, the appropriate error function is called. Also, if theconnection has been closed, the closed() function is called to the itdeal with the event.Next, the function checks if the connection has just been establishedby checking if uip_connected() is true. The connected() function iscalled and is supposed to do whatever needs to be done when theconnection is established, such as intializing the application statefor the connection. Since it may be the case that data should be sentout, the senddata() function is called to deal with the outgoing data.The following very simple application serves as an example of how theapplication handler functions might look. This application simplywaits for any data to arrive on the connection, and responds to thedata by sending out the message "Hello world!". To illustrate how todevelop an application state machine, this message is sent in twoparts, first the "Hello" part and then the "world!" part.\code#define STATE_WAITING 0#define STATE_HELLO 1#define STATE_WORLD 2struct example6_state {  u8_t state;  char *textptr;  int textlen;};static void aborted(void) {}static void timedout(void) {}static void closed(void) {}static void connected(void) {  struct example6_state *s = (struct example6_state *)uip_conn->appstate;  s->state = STATE_WAITING;  s->textlen = 0;}static void newdata(void) {  struct example6_state *s = (struct example6_state *)uip_conn->appstate;  if(s->state == STATE_WAITING) {    s->state = STATE_HELLO;    s->textptr = "Hello ";    s->textlen = 6;  }}static void acked(void) {  struct example6_state *s = (struct example6_state *)uip_conn->appstate;    s->textlen -= uip_conn->len;  s->textptr += uip_conn->len;  if(s->textlen == 0) {    switch(s->state) {    case STATE_HELLO:      s->state = STATE_WORLD;      s->textptr = "world!\n";      s->textlen = 7;      break;    case STATE_WORLD:      uip_close();      break;    }  }}static void senddata(void) {  struct example6_state *s = (struct example6_state *)uip_conn->appstate;  if(s->textlen > 0) {    uip_send(s->textptr, s->textlen);  }}\endcodeThe application state consists of a "state" variable, a "textptr"pointer to a text message and the "textlen" length of the textmessage. The "state" variable can be either "STATE_WAITING", meaningthat the application is waiting for data to arrive from the network,"STATE_HELLO", in which the application is sending the "Hello" part ofthe message, or "STATE_WORLD", in which the application is sending the"world!" message. The application does not handle errors or connection closing events,and therefore the aborted(), timedout() and closed() functions areimplemented as empty functions.The connected() function will be called when a connection has beenestablished, and in this case sets the "state" variable to be"STATE_WAITING" and the "textlen" variable to be zero, indicating thatthere is no message to be sent out.When new data arrives from the network, the newdata() function will becalled by the event handler function. The newdata() function willcheck if the connection is in the "STATE_WAITING" state, and if soswitches to the "STATE_HELLO" state and registers a 6 byte long "Hello" message with the connection. This message will later be sent out bythe senddata() function.The acked() function is called whenever data that previously was senthas been acknowleged by the receiving host. This acked() functionfirst reduces the amount of data that is left to send, by subtractingthe length of the previously sent data (obtained from "uip_conn->len")from the "textlen" variable, and also adjusts the "textptr" pointeraccordingly. It then checks if the "textlen" variable now is zero,which indicates that all data now has been successfully received, andif so changes application state. If the application was in the"STATE_HELLO" state, it switches state to "STATE_WORLD" and sets up a7 byte "world!\n" message to be sent. If the application was in the"STATE_WORLD" state, it closes the connection.Finally, the senddata() function takes care of actually sending thedata that is to be sent. It is called by the event handler functionwhen new data has been received, when data has been acknowledged, whena new connection has been established, when the connection is polledbecause of inactivity, or when a retransmission should be made. Thepurpose of the senddata() function is to optionally format the datathat is to be sent, and to call the uip_send() function to actuallysend out the data. In this particular example, the function simplycalls uip_send() with the appropriate arguments if data is to be sent,after checking if data should be sent out or not as indicated by the"textlen" variable.It is important to note that the senddata() function never shouldaffect the application state; this should only be done in the acked()and newdata() functions.\section protoimpl Protocol ImplementationsThe protocols in the TCP/IP protocol suite are designed in a layeredfashion where each protocol performs a specific function and theinteractions between the protocol layers are strictly defined. Whilethe layered approach is a good way to design protocols, it is notalways the best way to implement them. In uIP, the protocolimplementations are tightly coupled in order to save code space.This section gives detailed information on the specific protocolimplementations in uIP.\subsection ip IP --- Internet ProtocolWhen incoming packets are processed by uIP, the IP layer is the firstprotocol that examines the packet. The IP layer does a few simplechecks such as if the destination IP address of the incoming packetmatches any of the local IP address and verifies the IP headerchecksum. Since there are no IP options that are strictly required andbecause they are very uncommon, any IP options in received packets aredropped.\subsubsection ipreass IP Fragment ReassemblyIP fragment reassembly is implemented using a separate buffer thatholds the packet to be reassembled. An incoming fragment is copiedinto the right place in the buffer and a bit map is used to keep trackof which fragments have been received. Because the first byte of an IPfragment is aligned on an 8-byte boundary, the bit map requires asmall amount of memory. When all fragments have been reassembled, theresulting IP packet is passed to the transport layer. If all fragmentshave not been received within a specified time frame, the packet isdropped.The current implementation only has a single buffer for holdingpackets to be reassembled, and therefore does not support simultaneousreassembly of more than one packet. Since fragmented packets areuncommon, this ought to be a reasonable decision. Extending theimplementation to support multiple buffers would be straightforward,however.\subsubsection ipbroadcast Broadcasts and MulticastsIP has the ability to broadcast and multicast packets on the localnetwork. Such packets are addressed to special broadcast and multicastaddresses. Broadcast is used heavily in many UDP based protocols suchas the Microsoft Windows file-sharing SMB protocol. Multicast isprimarily used in protocols used for multimedia distribution such asRTP. TCP is a point-to-point protocol and does not use broadcast ormulticast packets. uIP current supports broadcast packets as well assending multicast packets. Joining multicast groups (IGMP) andreceiving non-local multicast packets is not currently supported.\subsection icmp ICMP --- Internet Control Message ProtocolThe ICMP protocol is used for reporting soft error conditions and forquerying host parameters. Its main use is, however, the echo mechanismwhich is used by the "ping" program.The ICMP implementation in uIP is very simple as itis restricted toonly implement ICMP echo messages. Replies to echo messages areconstructed by simply swapping the source and destination IP addressesof incoming echo requests and rewriting the ICMP header with theEcho-Reply message type. The ICMP checksum is adjusted using standardtechniques (see RFC1624).Since only the ICMP echo message is implemented, there is no supportfor Path MTU discovery or ICMP redirect messages. Neither of these isstrictly required for interoperability; they are performanceenhancement mechanisms.\subsection tcp TCP --- Transmission Control ProtocolThe TCP implementation in uIP is driven by incoming packets and timerevents. Incoming packets are parsed by TCP and if the packet containsdata that is to be delivered to the application, the application isinvoked by the means of the application function call. If the incomingpacket acknowledges previously sent data, the connection state isupdated and the application is informed, allowing it to send out newdata.\subsubsection listeb Listening ConnectionsTCP allows a connection to listen for incoming connection requests. InuIP, a listening connection is identified by the 16-bit port numberand incoming connection requests are checked against the list oflistening connections. This list of listening connections is dynamicand can be altered by the applications in the system.\subsubsection slidingwindow Sliding WindowMost TCP implementations use a sliding window mechanism for sendingdata. Multiple data segments are sent in succession without waitingfor an acknowledgment for each segment.The sliding window algorithm uses a lot of 32-bit operations andbecause 32-bit arithmetic is fairly expensive on most 8-bit CPUs, uIPdoes not implement it. Also, uIP does not buffer sent packets and asliding window implementation that does not buffer sent packets will haveto be supported by a complex application layer. Instead, uIP allowsonly a single TCP segment per connection to be unacknowledged at anygiven time.It is important to note that even though most TCP implementations usethe sliding window algorithm, it is not required by the TCPspecifications. Removing the sliding window mechanism does not affectinteroperability in any way.\subsubsection rttest Round-Trip Time EstimationTCP continuously estimates the current Round-Trip Time (RTT) of everyactive connection in order to find a suitable value for theretransmission time-out.The RTT estimation in uIP is implemented using TCP's periodictimer. Each time the periodic timer fires, it increments a counter foreach connection that has unacknowledged data in the network. When anacknowledgment is received, the current value of the counter is usedas a sample of the RTT. The sample is used together with VanJacobson's standard TCP RTT estimation function to calculate anestimate of the RTT. Karn's algorithm is used to ensure thatretransmissions do not skew the estimates.\subsubsection rexmit RetransmissionsRetransmissions are driven by the periodic TCP timer. Every time theperiodic timer is invoked, the retransmission timer for eachconnection is decremented. If the timer reaches zero, a retransmissionshould be made.As uIP does not keep track of packet contents after they havebeen sent by the device driver, uIP requires that theapplication takes an active part in performing theretransmission. When uIP decides that a segment should beretransmitted, it calls the application with a flag set indicatingthat a retransmission is required. The application checks theretransmission flag and produces the same data that was previouslysent. From the application's standpoint, performing a retransmissionis not different from how the data originally was sent. Therefore theapplication can be written in such a way that the same code is usedboth for sending data and retransmitting data. Also, it is importantto note that even though the actual retransmission operation iscarried out by the application, it is the responsibility of the stackto know when the retransmission should be made. Thus the complexity ofthe application does not necessarily increase because it takes anactive part in doing retransmissions.\subsubsection flowcontrol Flow ControlThe purpose of TCP's flow control mechanisms is to allow communicationbetween hosts with wildly varying memory dimensions. In each TCPsegment, the sender of the segment indicates its available bufferspace. A TCP sender must not send more data than the buffer spaceindicated by the receiver.In uIP, the application cannot send more data than the receiving hostcan buffer. And application cannot send more data than the amount ofbytes it is allowed to send by the receiving host. If the remote hostcannot accept any data at all, the stack initiates the zero windowprobing mechanism.\subsubsection congestioncontrol Congestion ControlThe congestion control mechanisms limit the number of simultaneous TCPsegments in the network. The algorithms used for congestion controlare designed to be simple to implement and require only a few lines ofcode.Since uIP only handles one in-flight TCP segment per connection,the amount of simultaneous segments cannot be further limited, thusthe congestion control mechanisms are not needed.\subsubsection urgdata Urgent DataTCP's urgent data mechanism provides an application-to-applicationnotification mechanism, which can be used by an application to markparts of the data stream as being more urgent than the normalstream. It is up to the receiving application to interpret the meaningof the urgent data.In many TCP implementations, including the BSD implementation, theurgent data feature increases the complexity of the implementationbecause it requires an asynchronous notification mechanism in anotherwise synchronous API. As uIP already use an asynchronous eventbased API, the implementation of the urgent data feature does not leadto increased complexity.\section performance PerformanceIn TCP/IP implementations for high-end systems, processing time isdominated by the checksum calculation loop, the operation of copyingpacket data and context switching. Operating systems for high-endsystems often have multiple protection domains for protecting kerneldata from user processes and user processes from each other. Becausethe TCP/IP stack is run in the kernel, data has to be copied betweenthe kernel space and the address space of the user processes and acontext switch has to be performed once the data has beencopied. Performance can be enhanced by combining the copy operationwith the checksum calculation. Because high-end systems usually havenumerous active connections, packet demultiplexing is also anexpensive operation.A small embedded device does not have the necessary processing powerto have multiple protection domains and the power to run amultitasking operating system. Therefore there is no need to copydata between the TCP/IP stack and the application program. With anevent based API there is no context switch between the TCP/IP stackand the applications.In such limited systems, the TCP/IP processing overhead is dominatedby the copying of packet data from the network device to host memory,and checksum calculation. Apart from the checksum calculation andcopying, the TCP processing done for an incoming packet involves onlyupdating a few counters and flags before handing the data over to theapplication. Thus an estimate of the CPU overhead of our TCP/IPimplementations can be obtained by calculating the amount of CPUcycles needed for the checksum calculation and copying of a maximumsized packet.\subsection delack The Impact of Delayed AcknowledgmentsMost TCP receivers implement the delayed acknowledgment algorithm forreducing the number of pure acknowledgment packets sent. A TCPreceiver using this algorithm will only send acknowledgments for everyother received segment. If no segment is received within a specifictime-frame, an acknowledgment is sent. The time-frame can be as highas 500 ms but typically is 200 ms.A TCP sender such as uIP that only handles a single outstanding TCPsegment will interact poorly with the delayed acknowledgmentalgorithm. Because the receiver only receives a single segment at atime, it will wait as much as 500 ms before an acknowledgment issent. This means that the maximum possible throughput is severelylimited by the 500 ms idle time.Thus the maximum throughput equation when sending data from uIP willbe $p = s / (t + t_d)$ where $s$ is the segment size and $t_d$ is thedelayed acknowledgment timeout, which typically is between 200 and500 ms. With a segment size of 1000 bytes, a round-trip time of 40 msand a delayed acknowledgment timeout of 200 ms, the maximumthroughput will be 4166 bytes per second. With the delayed acknowledgmentalgorithm disabled at the receiver, the maximum throughput would be25000 bytes per second.It should be noted, however, that since small systems running uIP arenot very likely to have large amounts of data to send, the delayedacknowledgmen t throughput degradation of uIP need not be verysevere. Small amounts of data sent by such a system will not span morethan a single TCP segment, and would therefore not be affected by thethroughput degradation anyway.The maximum throughput when uIP acts as a receiver is not affected bythe delayed acknowledgment throughput degradation.\note The \ref uipsplit module implements a hack that overcomes theproblems with the delayed acknowledgment throughput degradation.*//** @} *//** @} */
Something went wrong with that request. Please try again.