Contiki 2.6

uip-split.c

00001 /*
00002  * Copyright (c) 2004, Swedish Institute of Computer Science.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  * Author: Adam Dunkels <adam@sics.se>
00032  *
00033  * $Id: uip-split.c,v 1.3 2010/01/25 13:53:15 adamdunkels Exp $
00034  */
00035 
00036 #include <string.h>
00037 
00038 #include "net/uip-split.h"
00039 #include "net/uip.h"
00040 #include "net/uip-fw.h"
00041 #include "net/uip_arch.h"
00042 
00043 #include "net/tcpip.h"
00044 
00045 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
00046 
00047 /*-----------------------------------------------------------------------------*/
00048 void
00049 uip_split_output(void)
00050 {
00051 #if UIP_TCP
00052   uint16_t tcplen, len1, len2;
00053 
00054   /* We only try to split maximum sized TCP segments. */
00055   if(BUF->proto == UIP_PROTO_TCP &&
00056      uip_len == UIP_TCP_MSS + UIP_TCPIP_HLEN) {
00057 
00058     tcplen = uip_len - UIP_TCPIP_HLEN;
00059     /* Split the segment in two. If the original packet length was
00060        odd, we make the second packet one byte larger. */
00061     len1 = len2 = tcplen / 2;
00062     if(len1 + len2 < tcplen) {
00063       ++len2;
00064     }
00065 
00066     /* Create the first packet. This is done by altering the length
00067        field of the IP header and updating the checksums. */
00068     uip_len = len1 + UIP_TCPIP_HLEN;
00069 #if UIP_CONF_IPV6
00070     /* For IPv6, the IP length field does not include the IPv6 IP header
00071        length. */
00072     BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
00073     BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
00074 #else /* UIP_CONF_IPV6 */
00075     BUF->len[0] = uip_len >> 8;
00076     BUF->len[1] = uip_len & 0xff;
00077 #endif /* UIP_CONF_IPV6 */
00078     
00079     /* Recalculate the TCP checksum. */
00080     BUF->tcpchksum = 0;
00081     BUF->tcpchksum = ~(uip_tcpchksum());
00082 
00083 #if !UIP_CONF_IPV6
00084     /* Recalculate the IP checksum. */
00085     BUF->ipchksum = 0;
00086     BUF->ipchksum = ~(uip_ipchksum());
00087 #endif /* UIP_CONF_IPV6 */
00088     
00089     /* Transmit the first packet. */
00090     /*    uip_fw_output();*/
00091 #if UIP_CONF_IPV6
00092     tcpip_ipv6_output();
00093 #else
00094     tcpip_output();
00095 #endif /* UIP_CONF_IPV6 */
00096    
00097     /* Now, create the second packet. To do this, it is not enough to
00098        just alter the length field, but we must also update the TCP
00099        sequence number and point the uip_appdata to a new place in
00100        memory. This place is detemined by the length of the first
00101        packet (len1). */
00102     uip_len = len2 + UIP_TCPIP_HLEN;
00103 #if UIP_CONF_IPV6
00104     /* For IPv6, the IP length field does not include the IPv6 IP header
00105        length. */
00106     BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
00107     BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
00108 #else /* UIP_CONF_IPV6 */
00109     BUF->len[0] = uip_len >> 8;
00110     BUF->len[1] = uip_len & 0xff;
00111 #endif /* UIP_CONF_IPV6 */
00112     
00113     /*    uip_appdata += len1;*/
00114     memcpy(uip_appdata, (uint8_t *)uip_appdata + len1, len2);
00115 
00116     uip_add32(BUF->seqno, len1);
00117     BUF->seqno[0] = uip_acc32[0];
00118     BUF->seqno[1] = uip_acc32[1];
00119     BUF->seqno[2] = uip_acc32[2];
00120     BUF->seqno[3] = uip_acc32[3];
00121     
00122     /* Recalculate the TCP checksum. */
00123     BUF->tcpchksum = 0;
00124     BUF->tcpchksum = ~(uip_tcpchksum());
00125 
00126 #if !UIP_CONF_IPV6
00127     /* Recalculate the IP checksum. */
00128     BUF->ipchksum = 0;
00129     BUF->ipchksum = ~(uip_ipchksum());
00130 #endif /* UIP_CONF_IPV6 */
00131 
00132     /* Transmit the second packet. */
00133     /*    uip_fw_output();*/
00134 #if UIP_CONF_IPV6
00135     tcpip_ipv6_output();
00136 #else
00137     tcpip_output();
00138 #endif /* UIP_CONF_IPV6 */
00139     return;
00140   }
00141 #endif /* UIP_TCP */
00142 
00143   /*    uip_fw_output();*/
00144 #if UIP_CONF_IPV6
00145      tcpip_ipv6_output();
00146 #else
00147      tcpip_output();
00148 #endif /* UIP_CONF_IPV6 */
00149 }
00150 
00151 /*-----------------------------------------------------------------------------*/