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 /*-----------------------------------------------------------------------------*/