uip-split.c

Go to the documentation of this file.
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 uIP TCP/IP stack
00030  *
00031  * Author: Adam Dunkels <adam@sics.se>
00032  *
00033  * $Id: uip-split.c,v 1.2 2006/06/12 08:00:30 adam Exp $
00034  */
00035 
00036 #include <string.h>
00037 
00038 #include "uip-split.h"
00039 #include "uip.h"
00040 #include "uip-fw.h"
00041 #include "uip_arch.h"
00042 
00043 
00044 
00045 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
00046 
00047 /*-----------------------------------------------------------------------------*/
00048 void
00049 uip_split_output(void)
00050 {
00051   u16_t tcplen, len1, len2;
00052 
00053   /* We only try to split maximum sized TCP segments. */
00054   if(BUF->proto == UIP_PROTO_TCP &&
00055      uip_len == UIP_BUFSIZE - UIP_LLH_LEN) {
00056 
00057     tcplen = uip_len - UIP_TCPIP_HLEN;
00058     /* Split the segment in two. If the original packet length was
00059        odd, we make the second packet one byte larger. */
00060     len1 = len2 = tcplen / 2;
00061     if(len1 + len2 < tcplen) {
00062       ++len2;
00063     }
00064 
00065     /* Create the first packet. This is done by altering the length
00066        field of the IP header and updating the checksums. */
00067     uip_len = len1 + UIP_TCPIP_HLEN;
00068 #if UIP_CONF_IPV6
00069     /* For IPv6, the IP length field does not include the IPv6 IP header
00070        length. */
00071     BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
00072     BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
00073 #else /* UIP_CONF_IPV6 */
00074     BUF->len[0] = uip_len >> 8;
00075     BUF->len[1] = uip_len & 0xff;
00076 #endif /* UIP_CONF_IPV6 */
00077     
00078     /* Recalculate the TCP checksum. */
00079     BUF->tcpchksum = 0;
00080     BUF->tcpchksum = ~(uip_tcpchksum());
00081 
00082 #if !UIP_CONF_IPV6
00083     /* Recalculate the IP checksum. */
00084     BUF->ipchksum = 0;
00085     BUF->ipchksum = ~(uip_ipchksum());
00086 #endif /* UIP_CONF_IPV6 */
00087     
00088     /* Transmit the first packet. */
00089     /*    uip_fw_output();*/
00090     tcpip_output();
00091 
00092     /* Now, create the second packet. To do this, it is not enough to
00093        just alter the length field, but we must also update the TCP
00094        sequence number and point the uip_appdata to a new place in
00095        memory. This place is detemined by the length of the first
00096        packet (len1). */
00097     uip_len = len2 + UIP_TCPIP_HLEN;
00098 #if UIP_CONF_IPV6
00099     /* For IPv6, the IP length field does not include the IPv6 IP header
00100        length. */
00101     BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
00102     BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
00103 #else /* UIP_CONF_IPV6 */
00104     BUF->len[0] = uip_len >> 8;
00105     BUF->len[1] = uip_len & 0xff;
00106 #endif /* UIP_CONF_IPV6 */
00107     
00108     /*    uip_appdata += len1;*/
00109     memcpy(uip_appdata, (u8_t *)uip_appdata + len1, len2);
00110 
00111     uip_add32(BUF->seqno, len1);
00112     BUF->seqno[0] = uip_acc32[0];
00113     BUF->seqno[1] = uip_acc32[1];
00114     BUF->seqno[2] = uip_acc32[2];
00115     BUF->seqno[3] = uip_acc32[3];
00116     
00117     /* Recalculate the TCP checksum. */
00118     BUF->tcpchksum = 0;
00119     BUF->tcpchksum = ~(uip_tcpchksum());
00120 
00121 #if !UIP_CONF_IPV6
00122     /* Recalculate the IP checksum. */
00123     BUF->ipchksum = 0;
00124     BUF->ipchksum = ~(uip_ipchksum());
00125 #endif /* UIP_CONF_IPV6 */
00126 
00127     /* Transmit the second packet. */
00128     /*    uip_fw_output();*/
00129     tcpip_output();
00130   } else {
00131     /*    uip_fw_output();*/
00132     tcpip_output();
00133   }
00134      
00135 }
00136 /*-----------------------------------------------------------------------------*/