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