This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

Dependents:   MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more

libMiMic(MiMic library for mbed)は、WebService機能を提供するSDKです。 mbedでWebAPIに対応したネットワークデバイスを簡単に作ることが出来ます。

libMiMicはMiMic projectで開発しています。MiMic projectについてはこちらをご覧ください。 http://nyatla.jp/mimic/wp/

構成

libMiMicはmbedRTOS上で動作し、ユーザアプリケーションにAPIを提供します。コアAPIはC言語で記述されていますが、使用頻度の高いものについてはmbed向けのC++APIが準備されています。

/media/uploads/nyatla/libmimic-sdk.png

※libMiMicはmbedの標準イーサネットドライバをしようしていません。

標準イーサネットドライバと同時に使用することはできません。

  • MiMicIP - IPv4スタックです。レテンシとメモリ消費量を抑えたuipベースのライブラリです。
  • ARP/ICMP/UDP/TCP - 基礎的なソケットAPIを提供します。APIは独自です。
  • HTTP/1.1 Server - HTTP/1.1に対応したサーバです。マルチセッション・Chunked・持続性接続に対応しています。
  • HTTP Modules - HTTP/1.1の機能モジュールです。以下のモジュールがあります。
    • ROM file provider - ROMに格納したファイルイメージを公開します。
    • File system provider - mbedファイルシステムを公開します。
    • Onchip configuration - プログラムフラッシュを利用して設定を保存します。
    • MiMicVM processor - RPCリクエスト(MiMicVM)を処理します。
    • FileUpload - ファイルアップロードを受け取ります。
    • URL decoder - HTTPリクエストを解析します。
    • UPnP handler -UPnPメッセージを処理します。
    • WebSocket - Websocketサーバです。
  • mDNS - マルチキャストDNSサービスです。
  • UPnP - UPnP/1.0の機能を提供します。UPnP handlerと協調して動作します。(現在はデバイス探索(SSDP)・デスクリプション(Description)のみ実装してあります。)
  • DHCP/APIPA - ゼロコンフィギュレーション用のモジュールです。
  • HTTP/1.1 Client
  • mbed C++ class library - mbed向けのC++CPIです。C言語のものより簡単です。

対応機種

  • mbed(mbed LPC1768)
  • LPCXpresso1769

プログラム

Import programMiMicRemoteMCU-for-Mbed

MiMic RemoteMCU for mbed. This program provides MCU control API over REST API. It can control MCU from Javascript,PHP or any HTTP rest client directly. And, The application has self development environment.

Import programMbedFileServer

The program publishes files at local directory and SD filesystem. It is a full-fledged webServer somewhat.

サンプル

Import programMiMicSimpleHttpd

This is a simplest HTTP server made ​​of libMiMic. It will echo back a request path.

Import programUPnPBasicDevice

Simplest UPnP basic device example. This program to run UPnP basic device on the mbed.

Import programWebSocketSample

MiMicSDK Websocket module sample program.

Import programHttpClientSamlpe

A http client sample program.

Import programTcpSocketClientSamlpe

MiMicSDK Tcp client socket sample program.

Import programUdpSocketSamlpe

Udp socket sample program. This program will send back the received packet.

チュートリアル

English

libMiMic(MiMic library for mbed) is SDK which provides Webservice functions. It can be created networking device easily using mbed.

See more MiMic information, See MiMic project website. http://nyatla.jp/mimic/wp/

Structure

libMiMic run on mbed RTOS and provides networking API to user application. This library has C++ class API for the mbed, and low-level C language API.

/media/uploads/nyatla/libmimic-sdk.png

For WebService general, it can be written in a simple C + + API.

libMiMic does not have the standard Ethernet driver of mbed. It is not possible that will be used with the standard Ethernet driver.

  • MiMicIP - IPv4 protocol stack. This is based uip which is reduced memory and latency.
  • ARP / ICMP / UDP / TCP - Those are provide basic IP protocols.
  • HTTP/1.1 Server - The Http server compatible HTTP/1.1. It supports multi-session, chunked transport, persistent connection.
  • HTTP Modules - There are addon-module for HTTP server. The following modules.
    • ROM file module - Publish the file images in ROM.
    • File system module - Publish thefiles in mbed file system.
    • Onchip configuration module - To save the network settings to the program flash via REST.
    • MiMicVM module - To handle the (MiMicVM) RPC request.
    • FileUpload module - Accept a file via HTTP POST.
    • URL dedoce module - A versatility URL decoder.
    • UPnP handle module - To handle UPnP messages.
    • UPnP - This provides UPnP/1.0 device functions. It works together with UPnP handler.
    • Websocket - websocket (version13) server
  • mDNS Service - DNS-SD protocol server.
  • UPnP - This provides UPnP/1.0 device functions which works with UPnP handler. (You have been implemented (SSDP) ? description only (Description) device search now.) It is a module zero configuration for - DHCP / APIPA. mbed C + + class library - C of mbed for + + is the CPI. It is simple than that of the C language.
  • DHCP/APIPA - It support zero-cpnfigulation.
  • mbed C++ class library. Almost APIs for Web applications are available.
  • HTTP/1.1 Client

Supported target

  • mbed(mbed LPC1768)
  • LPCXpresso1769

Application

Import programMiMicRemoteMCU-for-Mbed

MiMic RemoteMCU for mbed. This program provides MCU control API over REST API. It can control MCU from Javascript,PHP or any HTTP rest client directly. And, The application has self development environment.

Import programMbedFileServer

The program publishes files at local directory and SD filesystem. It is a full-fledged webServer somewhat.

Sample

Import programMiMicSimpleHttpd

This is a simplest HTTP server made ​​of libMiMic. It will echo back a request path.

Import programUPnPBasicDevice

Simplest UPnP basic device example. This program to run UPnP basic device on the mbed.

Import programWebSocketSample

MiMicSDK Websocket module sample program.

Import programHttpClientSamlpe

A http client sample program.

Import programTcpSocketClientSamlpe

MiMicSDK Tcp client socket sample program.

Import programUdpSocketSamlpe

Udp socket sample program. This program will send back the received packet.

Tutorial

Committer:
nyatla
Date:
Thu May 29 14:29:15 2014 +0000
Revision:
69:8c5f220441f5
Parent:
63:157ee3202edb
r354????; LPC4088?????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nyatla 0:142ee8b12fef 1 /*********************************************************************************
nyatla 0:142ee8b12fef 2 * PROJECT: MiMic
nyatla 0:142ee8b12fef 3 * --------------------------------------------------------------------------------
nyatla 0:142ee8b12fef 4 *
nyatla 0:142ee8b12fef 5 * This file is part of MiMic
nyatla 0:142ee8b12fef 6 * Copyright (C)2011 Ryo Iizuka
nyatla 0:142ee8b12fef 7 *
nyatla 0:142ee8b12fef 8 * MiMic is free software: you can redistribute it and/or modify
nyatla 0:142ee8b12fef 9 * it under the terms of the GNU Lesser General Public License as published
nyatla 0:142ee8b12fef 10 * by the Free Software Foundation, either version 3 of the License, or
nyatla 0:142ee8b12fef 11 * (at your option) any later version.
nyatla 0:142ee8b12fef 12 *
nyatla 0:142ee8b12fef 13 * This program is distributed in the hope that it will be useful,
nyatla 0:142ee8b12fef 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nyatla 0:142ee8b12fef 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
nyatla 0:142ee8b12fef 16 * GNU General Public License for more details.
nyatla 0:142ee8b12fef 17 *
nyatla 0:142ee8b12fef 18 * You should have received a copy of the GNU Lesser General Public License
nyatla 0:142ee8b12fef 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
nyatla 0:142ee8b12fef 20 *
nyatla 0:142ee8b12fef 21 * For further information please contact.
nyatla 0:142ee8b12fef 22 * http://nyatla.jp/
nyatla 0:142ee8b12fef 23 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
nyatla 0:142ee8b12fef 24 *
nyatla 0:142ee8b12fef 25 *********************************************************************************/
nyatla 0:142ee8b12fef 26 #include "NyLPC_cTcpSocket_protected.h"
nyatla 0:142ee8b12fef 27 #include "NyLPC_stdlib.h"
nyatla 0:142ee8b12fef 28 #include "NyLPC_cUipService_protected.h"
nyatla 0:142ee8b12fef 29
nyatla 0:142ee8b12fef 30
nyatla 0:142ee8b12fef 31 static NyLPC_TUInt32 iss32=3939;
nyatla 0:142ee8b12fef 32 #define SIZE_OF_IPv4_TCPIP_HEADER 40
nyatla 0:142ee8b12fef 33
nyatla 57:bc4330dfa62f 34 /**
nyatla 57:bc4330dfa62f 35 * TCPのRTOの最大値。
nyatla 57:bc4330dfa62f 36 * ms単位である。
nyatla 57:bc4330dfa62f 37 * defaultは64SEC
nyatla 57:bc4330dfa62f 38 */
nyatla 57:bc4330dfa62f 39 #define UIP_IP_RTO_MAX_RTO 64000
nyatla 57:bc4330dfa62f 40 /**
nyatla 57:bc4330dfa62f 41 * TCPのRTOの初期値。
nyatla 57:bc4330dfa62f 42 * ms単位である。
nyatla 57:bc4330dfa62f 43 * 伝送路の特性に合わせて調整すること。
nyatla 57:bc4330dfa62f 44 */
nyatla 57:bc4330dfa62f 45 #define UIP_TCP_RTO_INITIAL 3000
nyatla 57:bc4330dfa62f 46
nyatla 57:bc4330dfa62f 47 /**
nyatla 57:bc4330dfa62f 48 * CONNECTION時のRTO
nyatla 57:bc4330dfa62f 49 */
nyatla 57:bc4330dfa62f 50 #define UIP_TCP_RTO_CONNECTION_INITIAL 200
nyatla 57:bc4330dfa62f 51
nyatla 57:bc4330dfa62f 52 /**
nyatla 57:bc4330dfa62f 53 * 下限値
nyatla 57:bc4330dfa62f 54 */
nyatla 57:bc4330dfa62f 55 #define UIP_TCP_RTO_MINIMUM 100
nyatla 57:bc4330dfa62f 56
nyatla 0:142ee8b12fef 57
nyatla 0:142ee8b12fef 58 /**
nyatla 0:142ee8b12fef 59 * for Debug
nyatla 0:142ee8b12fef 60 * RTOの情報をログ領域に取る。
nyatla 0:142ee8b12fef 61 */
nyatla 0:142ee8b12fef 62 #ifdef RTO_LOG
nyatla 0:142ee8b12fef 63 NyLPC_TUInt32 rto_log[256];
nyatla 0:142ee8b12fef 64 int rto_log_st=0;
nyatla 0:142ee8b12fef 65 #define DEBUG_RTO_LOG(i_inst) if(rto_log_st<256){rto_log[rto_log_st++]=i_inst->uip_connr.current_rto32;};
nyatla 0:142ee8b12fef 66 #else
nyatla 0:142ee8b12fef 67 #define DEBUG_RTO_LOG(i_inst)
nyatla 0:142ee8b12fef 68 #endif
nyatla 0:142ee8b12fef 69
nyatla 37:fc4b4fd6a649 70 //#define lockResource(i_inst) NyLPC_cMutex_lock(&((i_inst)->_smutex))
nyatla 37:fc4b4fd6a649 71 //#define unlockResource(i_inst) NyLPC_cMutex_unlock(&((i_inst)->_smutex))
nyatla 57:bc4330dfa62f 72 #define lockResource(i_inst) NyLPC_cMutex_lock(NyLPC_cIPv4_getSockMutex(((i_inst)->_super._parent_ipv4)))
nyatla 57:bc4330dfa62f 73 #define unlockResource(i_inst) NyLPC_cMutex_unlock(NyLPC_cIPv4_getSockMutex(((i_inst)->_super._parent_ipv4)))
nyatla 37:fc4b4fd6a649 74
nyatla 0:142ee8b12fef 75 static void sendRst(NyLPC_TcTcpSocket_t* i_inst);
nyatla 0:142ee8b12fef 76
nyatla 0:142ee8b12fef 77
nyatla 69:8c5f220441f5 78
nyatla 69:8c5f220441f5 79
nyatla 69:8c5f220441f5 80 ////////////////////////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 81 //
nyatla 69:8c5f220441f5 82 // Packet writer
nyatla 69:8c5f220441f5 83 //
nyatla 69:8c5f220441f5 84 ////////////////////////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 85
nyatla 69:8c5f220441f5 86
nyatla 0:142ee8b12fef 87 /**
nyatla 69:8c5f220441f5 88 * TCPヘッダに値をセットする。checksum,wndは0初期化する。
nyatla 0:142ee8b12fef 89 */
nyatla 69:8c5f220441f5 90 static void setTcpTxHeader(struct NyLPC_TTcpHeader* i_struct,NyLPC_TUInt8 i_flag,const struct uip_conn* i_conn)
nyatla 69:8c5f220441f5 91 {
nyatla 69:8c5f220441f5 92 i_struct->flags = i_flag;
nyatla 69:8c5f220441f5 93 //sorce & destination port
nyatla 69:8c5f220441f5 94 i_struct->srcport = i_conn->lport;
nyatla 69:8c5f220441f5 95 i_struct->destport = i_conn->rport;
nyatla 69:8c5f220441f5 96 //ACK number
nyatla 69:8c5f220441f5 97 i_struct->ackno32 = NyLPC_htonl(i_conn->rcv_nxt32);
nyatla 69:8c5f220441f5 98 //Seq Number
nyatla 69:8c5f220441f5 99 i_struct->seqno32 = NyLPC_htonl(i_conn->snd_nxt32);
nyatla 69:8c5f220441f5 100 //uip_func_tcp_send_noconn(BUF);
nyatla 69:8c5f220441f5 101 i_struct->urgp[0] = i_struct->urgp[1] = 0;
nyatla 69:8c5f220441f5 102 i_struct->tcpchksum= 0;
nyatla 69:8c5f220441f5 103 }
nyatla 69:8c5f220441f5 104
nyatla 69:8c5f220441f5 105 static void setTxPacket(const NyLPC_TcTcpSocket_t* i_inst,void* i_tx_buf,NyLPC_TUInt8 i_tcpf,const void* i_buf,NyLPC_TUInt16 i_len)
nyatla 0:142ee8b12fef 106 {
nyatla 69:8c5f220441f5 107 struct NyLPC_TIPv4Header* iph;
nyatla 69:8c5f220441f5 108 struct NyLPC_TTcpHeader* tcph;
nyatla 69:8c5f220441f5 109 NyLPC_TUInt8 iph_word=0x05;
nyatla 69:8c5f220441f5 110 NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
nyatla 69:8c5f220441f5 111 //IPヘッダの更新
nyatla 69:8c5f220441f5 112 iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
nyatla 69:8c5f220441f5 113 iph->vhl=0x40|(0x0f&iph_word);
nyatla 69:8c5f220441f5 114 iph->destipaddr=i_inst->uip_connr.ripaddr;
nyatla 69:8c5f220441f5 115 iph->srcipaddr =*(i_inst->uip_connr.lipaddr);
nyatla 69:8c5f220441f5 116 NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
nyatla 69:8c5f220441f5 117 //TCPヘッダの更新
nyatla 69:8c5f220441f5 118 tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
nyatla 69:8c5f220441f5 119
nyatla 69:8c5f220441f5 120
nyatla 69:8c5f220441f5 121 //SYNが有るならMSSの書き込み
nyatla 69:8c5f220441f5 122 if((TCP_SYN & i_tcpf)){
nyatla 69:8c5f220441f5 123 tcph_word+=((TCP_OPT_MSS_LEN) / 4);
nyatla 69:8c5f220441f5 124 NyLPC_TTcpHeader_setMmsOpt(((NyLPC_TUInt8*)(tcph+1)),i_inst->uip_connr.default_mss);
nyatla 0:142ee8b12fef 125 }
nyatla 69:8c5f220441f5 126 tcph->tcpoffset=(tcph_word<<4);
nyatla 69:8c5f220441f5 127 setTcpTxHeader(tcph,i_tcpf,&(i_inst->uip_connr));
nyatla 69:8c5f220441f5 128
nyatla 69:8c5f220441f5 129 //最終的なパケットサイズと必要ならペイロードを書き込み
nyatla 69:8c5f220441f5 130 if(i_buf!=NULL){
nyatla 69:8c5f220441f5 131 iph->len16=NyLPC_htons(i_len+(iph_word+tcph_word)*4);
nyatla 69:8c5f220441f5 132 memcpy(((NyLPC_TUInt8*)i_tx_buf)+((iph_word+tcph_word)*4),i_buf,i_len);
nyatla 69:8c5f220441f5 133 }else{
nyatla 69:8c5f220441f5 134 iph->len16=NyLPC_htons((iph_word+tcph_word)*4);
nyatla 69:8c5f220441f5 135 }
nyatla 69:8c5f220441f5 136 //WND設定
nyatla 69:8c5f220441f5 137 tcph->wnd16=NyLPC_htons(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf)));
nyatla 69:8c5f220441f5 138 //Checksumの生成
nyatla 69:8c5f220441f5 139 tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
nyatla 69:8c5f220441f5 140 iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
nyatla 0:142ee8b12fef 141 return;
nyatla 0:142ee8b12fef 142 }
nyatla 69:8c5f220441f5 143
nyatla 69:8c5f220441f5 144 /**
nyatla 69:8c5f220441f5 145 * IP/TCPヘッダが40バイト固定として、i_tx_buf+40の位置にあるペイロードに対するIP/TCPヘッダを書き込みます。
nyatla 69:8c5f220441f5 146 */
nyatla 69:8c5f220441f5 147 static void setTxPacketHeader(const NyLPC_TcTcpSocket_t* i_inst,void* i_tx_buf,NyLPC_TUInt8 i_tcpf,NyLPC_TUInt16 i_len)
nyatla 69:8c5f220441f5 148 {
nyatla 69:8c5f220441f5 149 struct NyLPC_TIPv4Header* iph;
nyatla 69:8c5f220441f5 150 struct NyLPC_TTcpHeader* tcph;
nyatla 69:8c5f220441f5 151 NyLPC_TUInt8 iph_word=0x05;
nyatla 69:8c5f220441f5 152 NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
nyatla 69:8c5f220441f5 153 //IPヘッダの更新
nyatla 69:8c5f220441f5 154 iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
nyatla 69:8c5f220441f5 155 iph->vhl=0x40|(0x0f&iph_word);
nyatla 69:8c5f220441f5 156 iph->destipaddr=i_inst->uip_connr.ripaddr;
nyatla 69:8c5f220441f5 157 iph->srcipaddr =*(i_inst->uip_connr.lipaddr);
nyatla 69:8c5f220441f5 158 NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
nyatla 69:8c5f220441f5 159
nyatla 69:8c5f220441f5 160 //TCPヘッダの更新
nyatla 69:8c5f220441f5 161 tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
nyatla 69:8c5f220441f5 162 tcph->tcpoffset=(tcph_word<<4);
nyatla 69:8c5f220441f5 163 setTcpTxHeader(tcph,i_tcpf,&(i_inst->uip_connr));
nyatla 69:8c5f220441f5 164
nyatla 69:8c5f220441f5 165 //最終的なパケットサイズと必要ならペイロードを書き込み
nyatla 69:8c5f220441f5 166 iph->len16=NyLPC_htons(i_len+(iph_word+tcph_word)*4);
nyatla 69:8c5f220441f5 167 //WND設定
nyatla 69:8c5f220441f5 168 tcph->wnd16=NyLPC_htons(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf)));
nyatla 69:8c5f220441f5 169 //Checksumの生成
nyatla 69:8c5f220441f5 170 tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
nyatla 69:8c5f220441f5 171 iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
nyatla 69:8c5f220441f5 172 return;
nyatla 69:8c5f220441f5 173 }
nyatla 69:8c5f220441f5 174
nyatla 69:8c5f220441f5 175
nyatla 69:8c5f220441f5 176
nyatla 69:8c5f220441f5 177
nyatla 69:8c5f220441f5 178
nyatla 69:8c5f220441f5 179 ////////////////////////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 180 //
nyatla 69:8c5f220441f5 181 // Mainclass::private
nyatla 69:8c5f220441f5 182 //
nyatla 69:8c5f220441f5 183 ////////////////////////////////////////////////////////////////////////////////////////////////////
nyatla 69:8c5f220441f5 184
nyatla 69:8c5f220441f5 185 /**
nyatla 69:8c5f220441f5 186 * ACK番号を更新する。
nyatla 69:8c5f220441f5 187 * @param i_ackno
nyatla 69:8c5f220441f5 188 * ネットワークオーダーのACK番号
nyatla 69:8c5f220441f5 189 */
nyatla 69:8c5f220441f5 190 static void updateAckNo(void* i_tx_buf,NyLPC_TUInt32 i_ackno)
nyatla 69:8c5f220441f5 191 {
nyatla 69:8c5f220441f5 192 struct NyLPC_TIPv4Header* iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
nyatla 69:8c5f220441f5 193 struct NyLPC_TTcpHeader* tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
nyatla 69:8c5f220441f5 194
nyatla 69:8c5f220441f5 195 /* union{
nyatla 69:8c5f220441f5 196 NyLPC_TUInt32 l;
nyatla 69:8c5f220441f5 197 NyLPC_TUInt8 b[4];
nyatla 69:8c5f220441f5 198 }old_ack,new_ack;
nyatla 69:8c5f220441f5 199 NyLPC_TUInt16 v1;
nyatla 69:8c5f220441f5 200 //checksumの計算
nyatla 69:8c5f220441f5 201 old_ack.l=i_inst->payload.tcp->ackno32;//古いACK番号
nyatla 69:8c5f220441f5 202 new_ack.l=i_ackno;//新しいACK番号
nyatla 69:8c5f220441f5 203 v1=NyLPC_ntohs(~(i_inst->payload.tcp->tcpchksum));//1の補数を取って、ホストオーダーに戻す。
nyatla 69:8c5f220441f5 204 //減算
nyatla 69:8c5f220441f5 205 v1=sub16c(v1,(old_ack.b[0]<<8)+old_ack.b[1]);
nyatla 69:8c5f220441f5 206 v1=sub16c(v1,(old_ack.b[2]<<8)+old_ack.b[3]);
nyatla 69:8c5f220441f5 207 //加算
nyatla 69:8c5f220441f5 208 v1=add16c(v1,(new_ack.b[0]<<8)+new_ack.b[1]);
nyatla 69:8c5f220441f5 209 v1=add16c(v1,(new_ack.b[2]<<8)+new_ack.b[3]);
nyatla 69:8c5f220441f5 210 v1=~NyLPC_htons(v1);*/
nyatla 69:8c5f220441f5 211 NyLPC_Trace();
nyatla 69:8c5f220441f5 212 tcph->ackno32=i_ackno;
nyatla 69:8c5f220441f5 213 NyLPC_Trace();
nyatla 69:8c5f220441f5 214 tcph->tcpchksum = 0;
nyatla 69:8c5f220441f5 215 NyLPC_Trace();
nyatla 69:8c5f220441f5 216 tcph->tcpchksum = ~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
nyatla 69:8c5f220441f5 217 NyLPC_Trace();
nyatla 69:8c5f220441f5 218
nyatla 69:8c5f220441f5 219 /*
nyatla 69:8c5f220441f5 220 if((i_inst->payload.tcp->tcpchksum!=v1)){
nyatla 69:8c5f220441f5 221 NyLPC_Warning();
nyatla 69:8c5f220441f5 222 }*/
nyatla 69:8c5f220441f5 223 }
nyatla 69:8c5f220441f5 224
nyatla 69:8c5f220441f5 225
nyatla 69:8c5f220441f5 226
nyatla 0:142ee8b12fef 227 /**
nyatla 0:142ee8b12fef 228 * 指定した送信パケットがACK済であるか調べる。
nyatla 0:142ee8b12fef 229 */
nyatla 0:142ee8b12fef 230 static NyLPC_TBool isPacketAcked(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq)
nyatla 0:142ee8b12fef 231 {
nyatla 0:142ee8b12fef 232 int rp;
nyatla 0:142ee8b12fef 233 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 234 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 235 while(rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 236 if(q[rp].ackno==i_sq){
nyatla 0:142ee8b12fef 237 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 238 }
nyatla 0:142ee8b12fef 239 rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 240 }
nyatla 0:142ee8b12fef 241 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 242 }
nyatla 0:142ee8b12fef 243 /**
nyatla 0:142ee8b12fef 244 * 送信キューからi_sq以前に送信したパケットを除外して、残り個数を返却する。
nyatla 0:142ee8b12fef 245 */
nyatla 0:142ee8b12fef 246 static int getNumOfSending(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq)
nyatla 0:142ee8b12fef 247 {
nyatla 0:142ee8b12fef 248 int rp,n;
nyatla 0:142ee8b12fef 249 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 250 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 251 n=0;
nyatla 0:142ee8b12fef 252 while(rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 253 if(q[rp].ackno==i_sq){
nyatla 0:142ee8b12fef 254 return n;
nyatla 0:142ee8b12fef 255 }
nyatla 0:142ee8b12fef 256 n++;
nyatla 0:142ee8b12fef 257 rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 258 }
nyatla 0:142ee8b12fef 259 return n;
nyatla 0:142ee8b12fef 260 }
nyatla 0:142ee8b12fef 261 /**
nyatla 0:142ee8b12fef 262 * この関数は、コネクションをリセットします。
nyatla 0:142ee8b12fef 263 * ロック状態でコールしてください。
nyatla 0:142ee8b12fef 264 * 関数は、現在バッファにある再送信待ちデータを開放します。
nyatla 0:142ee8b12fef 265 */
nyatla 0:142ee8b12fef 266 static void resetTxQWithUnlock(NyLPC_TcTcpSocket_t* i_inst)
nyatla 0:142ee8b12fef 267 {
nyatla 0:142ee8b12fef 268 int i,l;
nyatla 0:142ee8b12fef 269 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 270 void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
nyatla 0:142ee8b12fef 271
nyatla 0:142ee8b12fef 272 l=0;
nyatla 0:142ee8b12fef 273 while(i_inst->txbuf.rp!=i_inst->txbuf.wp){
nyatla 69:8c5f220441f5 274 dlist[l]=q[i_inst->txbuf.rp].packet;
nyatla 0:142ee8b12fef 275 l++;
nyatla 0:142ee8b12fef 276 i_inst->txbuf.rp=(i_inst->txbuf.rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 277 }
nyatla 0:142ee8b12fef 278 i_inst->txbuf.rp=i_inst->txbuf.wp=0;
nyatla 0:142ee8b12fef 279 //ロック解除
nyatla 37:fc4b4fd6a649 280 unlockResource(i_inst);
nyatla 0:142ee8b12fef 281 //セーブしたバッファを開放
nyatla 0:142ee8b12fef 282 for(i=0;i<l;i++){
nyatla 0:142ee8b12fef 283 NyLPC_cUipService_releaseTxBuf(dlist[i]);
nyatla 0:142ee8b12fef 284 }
nyatla 0:142ee8b12fef 285 return;
nyatla 0:142ee8b12fef 286 }
nyatla 0:142ee8b12fef 287 /**
nyatla 0:142ee8b12fef 288 * TXバッファの再送パケットのACK番号を更新します。
nyatla 0:142ee8b12fef 289 * ロックして実行してください。
nyatla 0:142ee8b12fef 290 * @param i_ackno
nyatla 0:142ee8b12fef 291 * ネットワークオーダーのACK番号
nyatla 0:142ee8b12fef 292 */
nyatla 0:142ee8b12fef 293 static void updateTxAck(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_ackno)
nyatla 0:142ee8b12fef 294 {
nyatla 0:142ee8b12fef 295 NyLPC_TUInt8 rp;
nyatla 0:142ee8b12fef 296 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 297 NyLPC_ArgAssert(i_inst!=NULL);
nyatla 0:142ee8b12fef 298 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 299 while(rp!=i_inst->txbuf.wp){
nyatla 69:8c5f220441f5 300 updateAckNo(q[rp].packet,i_ackno);
nyatla 0:142ee8b12fef 301 rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 302 }
nyatla 0:142ee8b12fef 303 }
nyatla 0:142ee8b12fef 304
nyatla 0:142ee8b12fef 305 /**
nyatla 0:142ee8b12fef 306 * RTOの予測関数
nyatla 0:142ee8b12fef 307 */
nyatla 0:142ee8b12fef 308 static void estimateRTO(NyLPC_TcTcpSocket_t* i_inst,int s,int n)
nyatla 0:142ee8b12fef 309 {
nyatla 0:142ee8b12fef 310 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 311 NyLPC_TUInt32 cr_rtt_min,cr_rtt_max,sk_rto,new_rto,w;
nyatla 0:142ee8b12fef 312 int i;
nyatla 0:142ee8b12fef 313 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 314 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 315
nyatla 0:142ee8b12fef 316 sk_rto=i_inst->uip_connr.current_rto32;
nyatla 0:142ee8b12fef 317 //ACKされたパケットの個数は?
nyatla 0:142ee8b12fef 318 switch(n){
nyatla 0:142ee8b12fef 319 case 1:
nyatla 0:142ee8b12fef 320 NyLPC_cStopwatch_set(&sw,q[s].tick_of_sent);
nyatla 0:142ee8b12fef 321 cr_rtt_min=NyLPC_cStopwatch_elapseInMsec(&sw);
nyatla 0:142ee8b12fef 322 if(sk_rto<cr_rtt_min){
nyatla 0:142ee8b12fef 323 //現在のRTOよりも大きい→再送があった。(再送の理由が回線遅延によるものかわからないので、基本RTOを25%増やす。)
nyatla 0:142ee8b12fef 324 new_rto=sk_rto*10/8;
nyatla 0:142ee8b12fef 325 }else if(sk_rto/4<cr_rtt_min){
nyatla 0:142ee8b12fef 326 //現在のRTOの1/4< n < 現在のRTO 想定内の変動。1/8
nyatla 0:142ee8b12fef 327 new_rto=(sk_rto+(cr_rtt_min*3*7))/8;
nyatla 0:142ee8b12fef 328 }else{
nyatla 0:142ee8b12fef 329 //現在の1/4以下。RTOを再計算。 RTOが大きすぎるので再計算。(計測値を優先した現在値との平均値)
nyatla 0:142ee8b12fef 330 new_rto=(sk_rto+(cr_rtt_min*3*3))/4;
nyatla 0:142ee8b12fef 331 }
nyatla 0:142ee8b12fef 332 break;
nyatla 0:142ee8b12fef 333 default:
nyatla 0:142ee8b12fef 334 //複数のパケットなら、最大と最小の時刻を得る。
nyatla 0:142ee8b12fef 335 NyLPC_cStopwatch_set(&sw,q[s].tick_of_sent);
nyatla 0:142ee8b12fef 336 cr_rtt_min=cr_rtt_max=NyLPC_cStopwatch_elapseInMsec(&sw);
nyatla 0:142ee8b12fef 337 for(i=1;i<n;i++){
nyatla 0:142ee8b12fef 338 NyLPC_cStopwatch_set(&sw,q[(s+i)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ].tick_of_sent);
nyatla 0:142ee8b12fef 339 w=NyLPC_cStopwatch_elapseInMsec(&sw);
nyatla 0:142ee8b12fef 340 if(cr_rtt_min>w){
nyatla 0:142ee8b12fef 341 cr_rtt_min=w;
nyatla 0:142ee8b12fef 342 }
nyatla 0:142ee8b12fef 343 if(cr_rtt_max<w){
nyatla 0:142ee8b12fef 344 cr_rtt_max=w;
nyatla 0:142ee8b12fef 345 }
nyatla 0:142ee8b12fef 346 }
nyatla 0:142ee8b12fef 347 if(sk_rto<cr_rtt_min && sk_rto<cr_rtt_max){
nyatla 0:142ee8b12fef 348 //最大値,最小値とも現在のRTTより大きい→低速な回線を検出。
nyatla 0:142ee8b12fef 349 new_rto=cr_rtt_max*10/8;//最大経過時間の25%増しの時間を設定。
nyatla 0:142ee8b12fef 350 }else if(sk_rto/4<cr_rtt_min){
nyatla 0:142ee8b12fef 351 //現在のRTOの1/4< n < 現在のRTO 想定範囲内。1/8の加重平均で速度計算。
nyatla 0:142ee8b12fef 352 new_rto=(sk_rto+(cr_rtt_min*3*7))/8;
nyatla 0:142ee8b12fef 353 }else{
nyatla 0:142ee8b12fef 354 //現在の1/4以下。RTOが大きすぎるので再計算。(計測値を優先した加重平均)
nyatla 0:142ee8b12fef 355 new_rto=(sk_rto+(cr_rtt_min*3*3))/4;
nyatla 0:142ee8b12fef 356 }
nyatla 0:142ee8b12fef 357 break;
nyatla 0:142ee8b12fef 358 }
nyatla 0:142ee8b12fef 359 NyLPC_cStopwatch_finalize(&sw);
nyatla 57:bc4330dfa62f 360 if(new_rto<UIP_TCP_RTO_MINIMUM){
nyatla 57:bc4330dfa62f 361 new_rto=UIP_TCP_RTO_MINIMUM;
nyatla 0:142ee8b12fef 362 }
nyatla 0:142ee8b12fef 363 i_inst->uip_connr.current_rto32=new_rto;
nyatla 0:142ee8b12fef 364 }
nyatla 0:142ee8b12fef 365
nyatla 0:142ee8b12fef 366 /**
nyatla 0:142ee8b12fef 367 * TXキューから、入力されたシーケンス番号より前のパケットを除外します。
nyatla 0:142ee8b12fef 368 * リングバッファのrp->wp-1までをチェックして、sqに等しいi_sq以前のパケットバッファをo_dlistへ返します。
nyatla 0:142ee8b12fef 369 *
nyatla 0:142ee8b12fef 370 */
nyatla 0:142ee8b12fef 371 static int updateTxQByIndex(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,void* o_dlist[])
nyatla 0:142ee8b12fef 372 {
nyatla 0:142ee8b12fef 373 int rp,n;
nyatla 0:142ee8b12fef 374 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 375 //ロック状態なう
nyatla 0:142ee8b12fef 376 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 377 n=0;
nyatla 0:142ee8b12fef 378 //This is debug
nyatla 0:142ee8b12fef 379 DEBUG_RTO_LOG(i_inst);
nyatla 0:142ee8b12fef 380
nyatla 0:142ee8b12fef 381 while(rp!=i_inst->txbuf.wp){
nyatla 69:8c5f220441f5 382 o_dlist[n]=q[rp].packet;
nyatla 0:142ee8b12fef 383 if(q[rp].ackno==i_sq){
nyatla 0:142ee8b12fef 384 //i_inst->txbuf.rp->rpのパケットのRTOからbaseRTOの値を再計算。
nyatla 0:142ee8b12fef 385 estimateRTO(i_inst,i_inst->txbuf.rp,n+1);
nyatla 0:142ee8b12fef 386 i_inst->txbuf.rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 387 return n+1;
nyatla 0:142ee8b12fef 388 }
nyatla 0:142ee8b12fef 389 n++;
nyatla 0:142ee8b12fef 390 rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 391 }
nyatla 0:142ee8b12fef 392 return 0;
nyatla 0:142ee8b12fef 393 }
nyatla 0:142ee8b12fef 394
nyatla 0:142ee8b12fef 395
nyatla 0:142ee8b12fef 396
nyatla 0:142ee8b12fef 397 /**
nyatla 0:142ee8b12fef 398 * 空きキューを1個返します。
nyatla 0:142ee8b12fef 399 * 空きキューの
nyatla 0:142ee8b12fef 400 */
nyatla 0:142ee8b12fef 401 static struct NyLPC_TcTcpSocket_TxQItem* getTxQ(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TcStopwatch_t* i_timer)
nyatla 0:142ee8b12fef 402 {
nyatla 0:142ee8b12fef 403 int i;
nyatla 0:142ee8b12fef 404 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 58:03b89038b21a 405 do{
nyatla 0:142ee8b12fef 406 //クローズドに遷移してしまったら、エラーである。
nyatla 0:142ee8b12fef 407 if(i_inst->tcpstateflags==UIP_CLOSED){
nyatla 0:142ee8b12fef 408 return NULL;
nyatla 0:142ee8b12fef 409 }
nyatla 0:142ee8b12fef 410 //キューの空きをチェック。wp+1==rpなら、キューがいっぱい。rp==wpなら、キューが空。
nyatla 0:142ee8b12fef 411 if(((i_inst->txbuf.wp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ)==i_inst->txbuf.rp){
nyatla 0:142ee8b12fef 412 //一時的なアンロック
nyatla 37:fc4b4fd6a649 413 unlockResource(i_inst);
nyatla 0:142ee8b12fef 414 //タスクスイッチ
nyatla 0:142ee8b12fef 415 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 416 //ロック
nyatla 37:fc4b4fd6a649 417 lockResource(i_inst);
nyatla 0:142ee8b12fef 418 continue;
nyatla 0:142ee8b12fef 419 }
nyatla 0:142ee8b12fef 420 i=i_inst->txbuf.wp;
nyatla 0:142ee8b12fef 421 i_inst->txbuf.wp=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 422 return &(q[i]);
nyatla 58:03b89038b21a 423 }while(!NyLPC_cStopwatch_isExpired(i_timer));
nyatla 0:142ee8b12fef 424 //失敗。タイムアウト。
nyatla 0:142ee8b12fef 425 return NULL;
nyatla 0:142ee8b12fef 426 }
nyatla 0:142ee8b12fef 427
nyatla 0:142ee8b12fef 428
nyatla 0:142ee8b12fef 429
nyatla 0:142ee8b12fef 430
nyatla 0:142ee8b12fef 431
nyatla 0:142ee8b12fef 432
nyatla 0:142ee8b12fef 433 /**********************************************************************
nyatla 0:142ee8b12fef 434 * public 関数
nyatla 0:142ee8b12fef 435 **********************************************************************/
nyatla 0:142ee8b12fef 436
nyatla 0:142ee8b12fef 437 NyLPC_TBool NyLPC_cTcpSocket_initialize(NyLPC_TcTcpSocket_t* i_inst,void* i_rbuf,NyLPC_TUInt16 i_rbuf_len)
nyatla 0:142ee8b12fef 438 {
nyatla 0:142ee8b12fef 439 int i;
nyatla 0:142ee8b12fef 440 NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst;
nyatla 37:fc4b4fd6a649 441 NyLPC_cBaseSocket_initialize(&(i_inst->_super),NyLPC_TcBaseSocket_TYPEID_TCP_SOCK);
nyatla 0:142ee8b12fef 442 //uipサービスは初期化済であること。
nyatla 0:142ee8b12fef 443 NyLPC_Assert(NyLPC_TcUipService_isInitService());
nyatla 0:142ee8b12fef 444
nyatla 0:142ee8b12fef 445 NyLPC_cFifoBuffer_initialize(&(i_inst->rxbuf),i_rbuf,i_rbuf_len);
nyatla 37:fc4b4fd6a649 446 // NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(i_inst->_smutex)));//個別Mutex
nyatla 57:bc4330dfa62f 447 // i_inst->_smutex=NyLPC_cIPv4_getSockMutex(&(srv->_tcpv4));//共有Mutex
nyatla 0:142ee8b12fef 448 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 0:142ee8b12fef 449 i_inst->txbuf.rp=i_inst->txbuf.wp=0;
nyatla 0:142ee8b12fef 450 for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
nyatla 69:8c5f220441f5 451 i_inst->txbuf.txq[i].packet=NULL;
nyatla 0:142ee8b12fef 452 }
nyatla 0:142ee8b12fef 453 //管理リストへ登録。
nyatla 37:fc4b4fd6a649 454 return NyLPC_cIPv4_addSocket(&(srv->_tcpv4),&(i_inst->_super));
nyatla 0:142ee8b12fef 455 }
nyatla 2:b96c1e90d120 456 void NyLPC_cTcpSocket_finalize(NyLPC_TcTcpSocket_t* i_inst)
nyatla 0:142ee8b12fef 457 {
nyatla 0:142ee8b12fef 458 int i;
nyatla 0:142ee8b12fef 459 NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst;
nyatla 0:142ee8b12fef 460 NyLPC_Assert(NyLPC_TcUipService_isInitService());
nyatla 0:142ee8b12fef 461 //uipサービスは初期化済であること。
nyatla 37:fc4b4fd6a649 462 if(!NyLPC_cIPv4_removeSocket(&(srv->_tcpv4),&(i_inst->_super))){
nyatla 0:142ee8b12fef 463 //削除失敗、それは死を意味する。
nyatla 0:142ee8b12fef 464 NyLPC_Abort();
nyatla 0:142ee8b12fef 465 }
nyatla 0:142ee8b12fef 466 //開放漏れの保険
nyatla 0:142ee8b12fef 467 if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
nyatla 37:fc4b4fd6a649 468 lockResource(i_inst);
nyatla 0:142ee8b12fef 469 resetTxQWithUnlock(i_inst);
nyatla 0:142ee8b12fef 470 }
nyatla 0:142ee8b12fef 471 for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
nyatla 69:8c5f220441f5 472 i_inst->txbuf.txq[i].packet=NULL;
nyatla 0:142ee8b12fef 473 }
nyatla 0:142ee8b12fef 474 NyLPC_cFifoBuffer_finalize(&(i_inst->rxbuf));
nyatla 37:fc4b4fd6a649 475 // NyLPC_cMutex_finalize(&(i_inst->_smutex));
nyatla 37:fc4b4fd6a649 476 NyLPC_cBaseSocket_finalize(&(i_inst->_super));
nyatla 0:142ee8b12fef 477 return;
nyatla 0:142ee8b12fef 478 }
nyatla 0:142ee8b12fef 479
nyatla 37:fc4b4fd6a649 480
nyatla 43:a182f2b5ff41 481
nyatla 43:a182f2b5ff41 482 NyLPC_TBool NyLPC_cTcpSocket_listenSyn(NyLPC_TcTcpSocket_t* i_inst,const struct NyLPC_TTcpSocketSynParam* i_lq,NyLPC_TUInt16 i_lport)
nyatla 0:142ee8b12fef 483 {
nyatla 37:fc4b4fd6a649 484 // NyLPC_Assert(NyLPC_cMutex_isLocked(i_inst->_smutex));
nyatla 37:fc4b4fd6a649 485 lockResource(i_inst);
nyatla 0:142ee8b12fef 486 //ソケットが無効であること。
nyatla 0:142ee8b12fef 487 if(i_inst->tcpstateflags==UIP_CLOSED)
nyatla 0:142ee8b12fef 488 {
nyatla 37:fc4b4fd6a649 489 //localipとdefault_mmsは別枠で設定
nyatla 0:142ee8b12fef 490 /* Fill in the necessary fields for the new connection. */
nyatla 57:bc4330dfa62f 491 i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_INITIAL;
nyatla 43:a182f2b5ff41 492 i_inst->uip_connr.lport = i_lport;
nyatla 43:a182f2b5ff41 493 i_inst->uip_connr.rport = i_lq->rport;
nyatla 43:a182f2b5ff41 494 i_inst->uip_connr.ripaddr=i_lq->srcaddr;
nyatla 0:142ee8b12fef 495 i_inst->uip_connr.snd_nxt32=iss32;
nyatla 0:142ee8b12fef 496 /* rcv_nxt should be the seqno from the incoming packet + 1. */
nyatla 43:a182f2b5ff41 497 i_inst->uip_connr.rcv_nxt32= i_lq->rcv_nxt32;
nyatla 0:142ee8b12fef 498 //MSSの設定
nyatla 57:bc4330dfa62f 499 i_inst->uip_connr.peer_mss=(i_lq->mss!=0)?i_lq->mss:i_inst->uip_connr.default_mss;
nyatla 0:142ee8b12fef 500 i_inst->uip_connr.peer_win=0;
nyatla 0:142ee8b12fef 501 NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
nyatla 57:bc4330dfa62f 502 //ここでステータスがかわる。
nyatla 57:bc4330dfa62f 503 i_inst->tcpstateflags = UIP_SYN_RCVD;
nyatla 0:142ee8b12fef 504 //前回のデータが残っていた場合の保険
nyatla 0:142ee8b12fef 505 if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 506 resetTxQWithUnlock(i_inst);
nyatla 0:142ee8b12fef 507 }else{
nyatla 37:fc4b4fd6a649 508 unlockResource(i_inst);
nyatla 0:142ee8b12fef 509 }
nyatla 0:142ee8b12fef 510 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 511 }
nyatla 37:fc4b4fd6a649 512 unlockResource(i_inst);
nyatla 0:142ee8b12fef 513 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 514 }
nyatla 43:a182f2b5ff41 515
nyatla 43:a182f2b5ff41 516
nyatla 0:142ee8b12fef 517 /**
nyatla 0:142ee8b12fef 518 * sq番のTxがキューから消え去るのを待ちます。
nyatla 0:142ee8b12fef 519 * この関数は、アンロック状態でコールしてください。
nyatla 0:142ee8b12fef 520 * <div>
nyatla 0:142ee8b12fef 521 * パケットがキューからなくなる条件は、以下の2つです。
nyatla 0:142ee8b12fef 522 * <ul>
nyatla 0:142ee8b12fef 523 * <li>ACKを受信してパケットキューが更新された。</li>
nyatla 0:142ee8b12fef 524 * <li>RSTを受信して(CLOSEDに遷移して)、キューがクリアされた。</li>
nyatla 0:142ee8b12fef 525 * <li>送信タイムアウトで関数が(CLOSEDに遷移させて)キューをクリアした。</li>
nyatla 0:142ee8b12fef 526 * </ul>
nyatla 0:142ee8b12fef 527 * </div>
nyatla 0:142ee8b12fef 528 * @param i_wait_msec
nyatla 0:142ee8b12fef 529 * @return
nyatla 0:142ee8b12fef 530 * 1番目の条件でパケットが消失したときのみ、TRUEを返します。
nyatla 0:142ee8b12fef 531 * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
nyatla 0:142ee8b12fef 532 */
nyatla 0:142ee8b12fef 533 static NyLPC_TBool waitForTxRemove(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,NyLPC_TcStopwatch_t* i_timer)
nyatla 0:142ee8b12fef 534 {
nyatla 0:142ee8b12fef 535 NyLPC_TUInt8 f;
nyatla 37:fc4b4fd6a649 536 lockResource(i_inst);
nyatla 58:03b89038b21a 537 do{
nyatla 0:142ee8b12fef 538 //パケットが送信中か調べる。
nyatla 0:142ee8b12fef 539 if(!isPacketAcked(i_inst,i_sq)){
nyatla 0:142ee8b12fef 540 //まだある場合は、タスクスイッチを繰り返して消失を待つ。
nyatla 37:fc4b4fd6a649 541 unlockResource(i_inst);
nyatla 0:142ee8b12fef 542 NyLPC_cThread_yield();
nyatla 37:fc4b4fd6a649 543 lockResource(i_inst);
nyatla 0:142ee8b12fef 544 continue;
nyatla 0:142ee8b12fef 545 }
nyatla 0:142ee8b12fef 546 //なくなった場合は、原因を調べる。
nyatla 0:142ee8b12fef 547 f=i_inst->tcpstateflags;
nyatla 37:fc4b4fd6a649 548 unlockResource(i_inst);
nyatla 0:142ee8b12fef 549 return (f==UIP_CLOSED)?NyLPC_TBool_FALSE:NyLPC_TBool_TRUE;
nyatla 58:03b89038b21a 550 }while(!NyLPC_cStopwatch_isExpired(i_timer));
nyatla 37:fc4b4fd6a649 551 unlockResource(i_inst);
nyatla 0:142ee8b12fef 552 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 553 }
nyatla 0:142ee8b12fef 554
nyatla 0:142ee8b12fef 555
nyatla 0:142ee8b12fef 556 /**
nyatla 0:142ee8b12fef 557 * 再送信処理をセットして、パケットを送信します。
nyatla 0:142ee8b12fef 558 * この関数は「アンロック状態で」実行してください。
nyatla 0:142ee8b12fef 559 * @param i_len
nyatla 0:142ee8b12fef 560 * 送信データサイズを指定します。
nyatla 0:142ee8b12fef 561 * この番号は、シーケンス番号の加算値ではありませんので、注意をしてください。
nyatla 0:142ee8b12fef 562 * @return
nyatla 0:142ee8b12fef 563 * <ul>
nyatla 0:142ee8b12fef 564 * <li>n=-1:送信キューへの投入に失敗した。</li>
nyatla 0:142ee8b12fef 565 * <li>n>=0:nバイトのデータを送信キューへの投入することに成功した。</li>
nyatla 0:142ee8b12fef 566 * </ul>
nyatla 0:142ee8b12fef 567 * 送信キューに失敗する理由は2つあります。1つは、TXバッファがフルでタイムアウト。もうひとつは、非同期なコネクリョンのリセットです。
nyatla 0:142ee8b12fef 568 * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
nyatla 0:142ee8b12fef 569 */
nyatla 0:142ee8b12fef 570 static NyLPC_TInt32 sendWithRetransmit(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt8 i_tcpf,const void* i_buf,NyLPC_TUInt16 i_len,NyLPC_TcStopwatch_t* i_timer,NyLPC_TUInt32* o_ack)
nyatla 0:142ee8b12fef 571 {
nyatla 0:142ee8b12fef 572 struct NyLPC_TcTcpSocket_TxQItem* txq;
nyatla 0:142ee8b12fef 573 NyLPC_TUInt16 s;
nyatla 0:142ee8b12fef 574 void* buf;
nyatla 0:142ee8b12fef 575 NyLPC_TUInt32 next_ack;
nyatla 0:142ee8b12fef 576 //送信バッファを取得
nyatla 69:8c5f220441f5 577 //@bug オブションパケット送信時に4バイト足りないメモリ要求しない?問題になってないけど。
nyatla 20:3b0b444b4deb 578 for(;;){
nyatla 20:3b0b444b4deb 579 buf=NyLPC_cUipService_allocTxBuf(i_len+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
nyatla 20:3b0b444b4deb 580 if(buf!=NULL){
nyatla 20:3b0b444b4deb 581 break;
nyatla 20:3b0b444b4deb 582 }
nyatla 20:3b0b444b4deb 583 //タイムアウト確認
nyatla 20:3b0b444b4deb 584 if(NyLPC_cStopwatch_isExpired(i_timer)){
nyatla 20:3b0b444b4deb 585 return -1;
nyatla 20:3b0b444b4deb 586 }
nyatla 20:3b0b444b4deb 587 };
nyatla 37:fc4b4fd6a649 588 lockResource(i_inst);
nyatla 0:142ee8b12fef 589 //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
nyatla 0:142ee8b12fef 590 if(i_len>0){
nyatla 0:142ee8b12fef 591 while(i_inst->uip_connr.peer_win==0){
nyatla 37:fc4b4fd6a649 592 unlockResource(i_inst);
nyatla 0:142ee8b12fef 593 //時間切れならエラー。
nyatla 0:142ee8b12fef 594 if(NyLPC_cStopwatch_isExpired(i_timer)){
nyatla 0:142ee8b12fef 595 return -1;
nyatla 0:142ee8b12fef 596 }
nyatla 0:142ee8b12fef 597 NyLPC_cThread_yield();
nyatla 37:fc4b4fd6a649 598 lockResource(i_inst);
nyatla 0:142ee8b12fef 599 }
nyatla 0:142ee8b12fef 600 }
nyatla 0:142ee8b12fef 601 //送信キューの取得
nyatla 0:142ee8b12fef 602 txq=getTxQ(i_inst,i_timer);
nyatla 0:142ee8b12fef 603 //送信キューが取れなかった。
nyatla 0:142ee8b12fef 604 if(txq==NULL){
nyatla 0:142ee8b12fef 605 //シーケンス番号をロールバックできないので、エラーとする。
nyatla 37:fc4b4fd6a649 606 unlockResource(i_inst);
nyatla 0:142ee8b12fef 607 NyLPC_cUipService_releaseTxBuf(buf);
nyatla 0:142ee8b12fef 608 return -1;
nyatla 0:142ee8b12fef 609 }
nyatla 0:142ee8b12fef 610
nyatla 0:142ee8b12fef 611 //送信バッファを基準とした送信サイズを計算
nyatla 0:142ee8b12fef 612 s-=SIZE_OF_IPv4_TCPIP_HEADER;
nyatla 0:142ee8b12fef 613 //送信サイズよりMMSが小さければ、送信サイズを修正
nyatla 0:142ee8b12fef 614 if(i_inst->uip_connr.peer_mss<s){
nyatla 0:142ee8b12fef 615 s=i_inst->uip_connr.peer_mss;
nyatla 0:142ee8b12fef 616 }
nyatla 0:142ee8b12fef 617 //送信サイズよりpeerのウインドウサイズが小さければ修正
nyatla 0:142ee8b12fef 618 if(i_inst->uip_connr.peer_win<s){
nyatla 0:142ee8b12fef 619 s=i_inst->uip_connr.peer_win;
nyatla 0:142ee8b12fef 620 }
nyatla 0:142ee8b12fef 621 //送信サイズより、データサイズが小さければ、送信サイズを修正
nyatla 0:142ee8b12fef 622 if(i_len<s){
nyatla 0:142ee8b12fef 623 s=i_len;
nyatla 0:142ee8b12fef 624 }
nyatla 0:142ee8b12fef 625 //ACK番号の計算
nyatla 57:bc4330dfa62f 626 next_ack=i_inst->uip_connr.snd_nxt32+s+(((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00)?1:0);
nyatla 0:142ee8b12fef 627 txq->rto32=i_inst->uip_connr.current_rto32;
nyatla 0:142ee8b12fef 628 txq->tick_of_sent=NyLPC_cStopwatch_now();
nyatla 0:142ee8b12fef 629
nyatla 0:142ee8b12fef 630 //パケットの書き込み
nyatla 69:8c5f220441f5 631 setTxPacket(i_inst,buf,i_tcpf,i_buf,s);
nyatla 69:8c5f220441f5 632 txq->packet=buf;
nyatla 69:8c5f220441f5 633
nyatla 0:142ee8b12fef 634 //シーケンス番号の更新
nyatla 0:142ee8b12fef 635 i_inst->uip_connr.snd_nxt32=next_ack;
nyatla 0:142ee8b12fef 636 //Peerのウインドウサイズを更新
nyatla 0:142ee8b12fef 637 i_inst->uip_connr.peer_win-=s;
nyatla 0:142ee8b12fef 638 //ACK番号の返却
nyatla 0:142ee8b12fef 639 *o_ack=txq->ackno=NyLPC_HTONL(next_ack);
nyatla 37:fc4b4fd6a649 640 unlockResource(i_inst);
nyatla 0:142ee8b12fef 641 NyLPC_cUipService_sendIPv4Tx(buf);
nyatla 0:142ee8b12fef 642 return s;
nyatla 0:142ee8b12fef 643 }
nyatla 0:142ee8b12fef 644 /**
nyatla 0:142ee8b12fef 645 * RSTを1フレームだけ送信します。
nyatla 0:142ee8b12fef 646 * この関数は、クローズドステータスのソケットにしてからコールします。
nyatla 0:142ee8b12fef 647 * この関数は、アンロック状態でコールしてね。
nyatla 0:142ee8b12fef 648 */
nyatla 0:142ee8b12fef 649 static void sendRst(NyLPC_TcTcpSocket_t* i_inst)
nyatla 0:142ee8b12fef 650 {
nyatla 0:142ee8b12fef 651 void* buf;
nyatla 0:142ee8b12fef 652
nyatla 0:142ee8b12fef 653 NyLPC_Assert(i_inst->tcpstateflags==UIP_CLOSED);
nyatla 0:142ee8b12fef 654 //ペイロードライタの初期化
nyatla 0:142ee8b12fef 655
nyatla 20:3b0b444b4deb 656 //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。
nyatla 69:8c5f220441f5 657 buf=NyLPC_cUipService_allocSysTxBuf();
nyatla 37:fc4b4fd6a649 658 lockResource(i_inst);
nyatla 0:142ee8b12fef 659 i_inst->uip_connr.snd_nxt32++;
nyatla 37:fc4b4fd6a649 660 unlockResource(i_inst);
nyatla 69:8c5f220441f5 661 setTxPacket(i_inst,buf,TCP_RST|TCP_ACK,NULL,0);
nyatla 0:142ee8b12fef 662 NyLPC_cUipService_sendIPv4Tx(buf);
nyatla 0:142ee8b12fef 663 NyLPC_cUipService_releaseTxBuf(buf);
nyatla 0:142ee8b12fef 664 NyLPC_cIPv4Payload_finalize(&ipv4);
nyatla 0:142ee8b12fef 665 return;
nyatla 0:142ee8b12fef 666 }
nyatla 0:142ee8b12fef 667
nyatla 0:142ee8b12fef 668
nyatla 0:142ee8b12fef 669
nyatla 0:142ee8b12fef 670 /**
nyatla 37:fc4b4fd6a649 671 * 受信データをバッファに書き込む。
nyatla 0:142ee8b12fef 672 * 十分な空き領域がない場合、失敗する。
nyatla 0:142ee8b12fef 673 * この関数は、ロックして実行してください。
nyatla 0:142ee8b12fef 674 */
nyatla 69:8c5f220441f5 675 static NyLPC_TBool addRecvData(NyLPC_TcTcpSocket_t* i_inst,const void* i_data,NyLPC_TUInt16 i_data_size)
nyatla 0:142ee8b12fef 676 {
nyatla 0:142ee8b12fef 677 //受信データサイズを確認
nyatla 0:142ee8b12fef 678 if(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf))>=i_data_size){
nyatla 0:142ee8b12fef 679 //バッファに格納可能なら、格納。
nyatla 0:142ee8b12fef 680 NyLPC_cFifoBuffer_push(&(i_inst->rxbuf),i_data,i_data_size);
nyatla 0:142ee8b12fef 681 }else{
nyatla 0:142ee8b12fef 682 //エラー:ドロップする。
nyatla 0:142ee8b12fef 683 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 684 }
nyatla 57:bc4330dfa62f 685
nyatla 0:142ee8b12fef 686 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 687 }
nyatla 0:142ee8b12fef 688
nyatla 0:142ee8b12fef 689
nyatla 0:142ee8b12fef 690
nyatla 0:142ee8b12fef 691
nyatla 0:142ee8b12fef 692 /**
nyatla 0:142ee8b12fef 693 * Public function
nyatla 0:142ee8b12fef 694 */
nyatla 0:142ee8b12fef 695
nyatla 58:03b89038b21a 696 NyLPC_TBool NyLPC_cTcpSocket_connect(NyLPC_TcTcpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_peer_port,NyLPC_TUInt32 i_wait_in_msec)
nyatla 57:bc4330dfa62f 697 {
nyatla 57:bc4330dfa62f 698 volatile NyLPC_TUInt8 f;
nyatla 57:bc4330dfa62f 699 NyLPC_TUInt32 sq;
nyatla 57:bc4330dfa62f 700 NyLPC_TcStopwatch_t sw;
nyatla 57:bc4330dfa62f 701 NyLPC_TUInt16 lport;
nyatla 57:bc4330dfa62f 702 lockResource(i_inst);
nyatla 57:bc4330dfa62f 703 //ソケットが無効であること。
nyatla 57:bc4330dfa62f 704 if(i_inst->tcpstateflags!=UIP_CLOSED)
nyatla 57:bc4330dfa62f 705 {
nyatla 57:bc4330dfa62f 706 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 707 }
nyatla 57:bc4330dfa62f 708 //ポート番号の取得(lockResourceが他のソケットと共有なので、重複ポートの割当は起こりえない。でもちょっと注意して)
nyatla 57:bc4330dfa62f 709 lport=NyLPC_htons(NyLPC_cIPv4_getNewPortNumber(i_inst->_super._parent_ipv4));
nyatla 57:bc4330dfa62f 710 if(lport==0){
nyatla 57:bc4330dfa62f 711 NyLPC_OnErrorGoto(Error);
nyatla 57:bc4330dfa62f 712 }
nyatla 57:bc4330dfa62f 713 //connectの為の準備
nyatla 57:bc4330dfa62f 714
nyatla 57:bc4330dfa62f 715 //localipとdefault_mmsは別枠で設定
nyatla 57:bc4330dfa62f 716 /* Fill in the necessary fields for the new connection. */
nyatla 57:bc4330dfa62f 717 i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_CONNECTION_INITIAL;//RTOを短くしてARP発行時の再接続短縮を期待する。
nyatla 57:bc4330dfa62f 718 i_inst->uip_connr.lport = lport;
nyatla 57:bc4330dfa62f 719 i_inst->uip_connr.rport = NyLPC_htons(i_peer_port);
nyatla 57:bc4330dfa62f 720 i_inst->uip_connr.ripaddr=*i_addr;
nyatla 57:bc4330dfa62f 721 i_inst->uip_connr.snd_nxt32=iss32;//should be random
nyatla 57:bc4330dfa62f 722 /* rcv_nxt should be the seqno from the incoming packet + 1. */
nyatla 57:bc4330dfa62f 723 i_inst->uip_connr.rcv_nxt32=0;
nyatla 57:bc4330dfa62f 724 //MSSの設定
nyatla 57:bc4330dfa62f 725 i_inst->uip_connr.peer_mss=i_inst->uip_connr.default_mss;
nyatla 57:bc4330dfa62f 726 i_inst->uip_connr.peer_win=1;//periodicの再送信を期待するために相手のWindowサイズは1と仮定する。
nyatla 57:bc4330dfa62f 727 NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
nyatla 57:bc4330dfa62f 728 //ここでステータスがかわる。
nyatla 57:bc4330dfa62f 729 i_inst->tcpstateflags = UIP_SYN_SENT;
nyatla 57:bc4330dfa62f 730 //前回のデータが残っていた場合の保険
nyatla 57:bc4330dfa62f 731 if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
nyatla 57:bc4330dfa62f 732 resetTxQWithUnlock(i_inst);
nyatla 57:bc4330dfa62f 733 }else{
nyatla 57:bc4330dfa62f 734 unlockResource(i_inst);
nyatla 57:bc4330dfa62f 735 }
nyatla 57:bc4330dfa62f 736
nyatla 57:bc4330dfa62f 737 NyLPC_cStopwatch_initialize(&sw);
nyatla 57:bc4330dfa62f 738
nyatla 57:bc4330dfa62f 739 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 57:bc4330dfa62f 740 if(sendWithRetransmit(i_inst,TCP_SYN,NULL,0,&sw,&sq)==0){
nyatla 57:bc4330dfa62f 741 //ちょっと待つ。
nyatla 57:bc4330dfa62f 742 NyLPC_cThread_yield();
nyatla 57:bc4330dfa62f 743 //キューにあるTXが消えるのを待つ。
nyatla 57:bc4330dfa62f 744 if(waitForTxRemove(i_inst,sq,&sw)){
nyatla 57:bc4330dfa62f 745 //ACK受信に成功して、TXが消失
nyatla 57:bc4330dfa62f 746 NyLPC_cStopwatch_finalize(&sw);
nyatla 57:bc4330dfa62f 747 return NyLPC_TBool_TRUE;
nyatla 57:bc4330dfa62f 748 }
nyatla 57:bc4330dfa62f 749 }
nyatla 57:bc4330dfa62f 750 //ロックして、強制的なステータス遷移
nyatla 57:bc4330dfa62f 751 lockResource(i_inst);
nyatla 57:bc4330dfa62f 752 f=i_inst->tcpstateflags;
nyatla 57:bc4330dfa62f 753 if(f!=UIP_CLOSED){
nyatla 57:bc4330dfa62f 754 //もし、強制CLOSE遷移であれば、RSTも送信。
nyatla 57:bc4330dfa62f 755 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 57:bc4330dfa62f 756 unlockResource(i_inst);
nyatla 57:bc4330dfa62f 757 sendRst(i_inst);
nyatla 57:bc4330dfa62f 758 }else{
nyatla 57:bc4330dfa62f 759 unlockResource(i_inst);
nyatla 57:bc4330dfa62f 760 }
nyatla 57:bc4330dfa62f 761 return NyLPC_TBool_FALSE;
nyatla 57:bc4330dfa62f 762 Error:
nyatla 57:bc4330dfa62f 763 unlockResource(i_inst);
nyatla 57:bc4330dfa62f 764 return NyLPC_TBool_FALSE;
nyatla 57:bc4330dfa62f 765 }
nyatla 57:bc4330dfa62f 766
nyatla 0:142ee8b12fef 767 /**
nyatla 0:142ee8b12fef 768 * この関数は、UIP_SYN_RCVDステータスのソケットを、ESTABLISHEDへ遷移させます。
nyatla 0:142ee8b12fef 769 * cTcpListener_listen関数を通過したインスタンスに実行してください。
nyatla 0:142ee8b12fef 770 * この関数は、アプリケーションが呼び出します。
nyatla 0:142ee8b12fef 771 * @return
nyatla 0:142ee8b12fef 772 *
nyatla 0:142ee8b12fef 773 */
nyatla 0:142ee8b12fef 774 NyLPC_TBool NyLPC_cTcpSocket_accept(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
nyatla 0:142ee8b12fef 775 {
nyatla 0:142ee8b12fef 776 volatile NyLPC_TUInt8 f;
nyatla 0:142ee8b12fef 777 NyLPC_TUInt32 sq;
nyatla 0:142ee8b12fef 778 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 779
nyatla 0:142ee8b12fef 780 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 781 //ステータスチェック
nyatla 0:142ee8b12fef 782 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 783 switch(f)
nyatla 0:142ee8b12fef 784 {
nyatla 0:142ee8b12fef 785 case UIP_ESTABLISHED:
nyatla 0:142ee8b12fef 786 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 787 case UIP_SYN_RCVD:
nyatla 0:142ee8b12fef 788 //処理対象
nyatla 0:142ee8b12fef 789 break;
nyatla 0:142ee8b12fef 790 default:
nyatla 0:142ee8b12fef 791 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 792 }
nyatla 0:142ee8b12fef 793 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 0:142ee8b12fef 794 if(sendWithRetransmit(i_inst,TCP_SYN|TCP_ACK,NULL,0,&sw,&sq)==0){
nyatla 0:142ee8b12fef 795 //ちょっと待つ。
nyatla 0:142ee8b12fef 796 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 797 //キューにあるTXが消えるのを待つ。
nyatla 0:142ee8b12fef 798 if(waitForTxRemove(i_inst,sq,&sw)){
nyatla 0:142ee8b12fef 799 //ACK受信に成功して、TXが消失
nyatla 0:142ee8b12fef 800 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 801 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 802 }
nyatla 0:142ee8b12fef 803 }
nyatla 0:142ee8b12fef 804 //ロックして、強制的なステータス遷移
nyatla 37:fc4b4fd6a649 805 lockResource(i_inst);
nyatla 0:142ee8b12fef 806 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 807 if(f!=UIP_CLOSED){
nyatla 57:bc4330dfa62f 808 //もし、強制CLOSE遷移であれば、RSTも送信。
nyatla 0:142ee8b12fef 809 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 57:bc4330dfa62f 810 unlockResource(i_inst);
nyatla 0:142ee8b12fef 811 sendRst(i_inst);
nyatla 57:bc4330dfa62f 812 }else{
nyatla 57:bc4330dfa62f 813 unlockResource(i_inst);
nyatla 0:142ee8b12fef 814 }
nyatla 0:142ee8b12fef 815 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 816 }
nyatla 0:142ee8b12fef 817
nyatla 0:142ee8b12fef 818
nyatla 0:142ee8b12fef 819 /**
nyatla 0:142ee8b12fef 820 * この関数は、ソケットの受信バッファの読み取り位置と、読み出せるデータサイズを返却します。
nyatla 0:142ee8b12fef 821 * 関数はポインターを返却するだけで、バッファの読み取り位置をシークしません。
nyatla 0:142ee8b12fef 822 * シークするにはNyLPC_cTcpSocket_pseekを使います。
nyatla 0:142ee8b12fef 823 */
nyatla 0:142ee8b12fef 824 NyLPC_TInt32 NyLPC_cTcpSocket_precv(NyLPC_TcTcpSocket_t* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec)
nyatla 0:142ee8b12fef 825 {
nyatla 0:142ee8b12fef 826 volatile NyLPC_TUInt8 st;
nyatla 0:142ee8b12fef 827 NyLPC_TUInt16 rlen;
nyatla 0:142ee8b12fef 828 //タイマを生成
nyatla 0:142ee8b12fef 829 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 830 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 831
nyatla 0:142ee8b12fef 832 //ESTABLISHED以外の場合は、エラー。
nyatla 0:142ee8b12fef 833 NyLPC_cStopwatch_setNow(&sw);
nyatla 58:03b89038b21a 834 do{
nyatla 0:142ee8b12fef 835 //読み出しバッファ情報のコピー
nyatla 0:142ee8b12fef 836 //MUTEX LOCK
nyatla 37:fc4b4fd6a649 837 lockResource(i_inst);
nyatla 0:142ee8b12fef 838 st=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 839 rlen=NyLPC_cFifoBuffer_getLength(&(i_inst->rxbuf));
nyatla 0:142ee8b12fef 840 *o_buf_ptr=NyLPC_cFifoBuffer_getPtr(&(i_inst->rxbuf));
nyatla 0:142ee8b12fef 841 //MUTEX UNLOCK
nyatla 37:fc4b4fd6a649 842 unlockResource(i_inst);
nyatla 0:142ee8b12fef 843
nyatla 0:142ee8b12fef 844 //バッファが空の場合は、ステータスチェック。ESTABLISHEDでなければ、エラー(PASVCLOSE等の場合)
nyatla 0:142ee8b12fef 845 switch(st){
nyatla 0:142ee8b12fef 846 case UIP_ESTABLISHED:
nyatla 0:142ee8b12fef 847 if(rlen>0){
nyatla 0:142ee8b12fef 848 //バッファにパケットがあれば返却
nyatla 0:142ee8b12fef 849 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 850 return rlen;
nyatla 0:142ee8b12fef 851 }
nyatla 0:142ee8b12fef 852 break;
nyatla 0:142ee8b12fef 853 case UIP_CLOSE_WAIT:
nyatla 0:142ee8b12fef 854 if(rlen>0){
nyatla 0:142ee8b12fef 855 //バッファにパケットがあれば返却
nyatla 0:142ee8b12fef 856 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 857 return rlen;
nyatla 0:142ee8b12fef 858 }
nyatla 0:142ee8b12fef 859 //引き続きエラー処理
nyatla 0:142ee8b12fef 860 default:
nyatla 0:142ee8b12fef 861 //他の場合はエラー
nyatla 0:142ee8b12fef 862 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 863 return -1;
nyatla 0:142ee8b12fef 864 }
nyatla 0:142ee8b12fef 865 //タスクスイッチ
nyatla 0:142ee8b12fef 866 NyLPC_cThread_yield();
nyatla 58:03b89038b21a 867 }while(NyLPC_cStopwatch_elapseInMsec(&sw)<i_wait_msec);
nyatla 0:142ee8b12fef 868 //規定時間内に受信が成功しなかった。
nyatla 0:142ee8b12fef 869 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 870 return 0;
nyatla 0:142ee8b12fef 871 }
nyatla 0:142ee8b12fef 872 /**
nyatla 0:142ee8b12fef 873 * 受信バッファをシークします。
nyatla 0:142ee8b12fef 874 * シーク後に、遅延ACKを送出します。
nyatla 0:142ee8b12fef 875 */
nyatla 0:142ee8b12fef 876 void NyLPC_cTcpSocket_pseek(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt16 i_seek)
nyatla 0:142ee8b12fef 877 {
nyatla 0:142ee8b12fef 878 void* buf;
nyatla 0:142ee8b12fef 879 NyLPC_ArgAssert(i_seek<=NyLPC_cFifoBuffer_getLength(&(i_inst->rxbuf)));
nyatla 0:142ee8b12fef 880 if(i_seek==0){
nyatla 0:142ee8b12fef 881 return;
nyatla 0:142ee8b12fef 882 }
nyatla 0:142ee8b12fef 883
nyatla 0:142ee8b12fef 884 //ACK送信バッファの取得
nyatla 69:8c5f220441f5 885 buf=NyLPC_cUipService_allocSysTxBuf();
nyatla 0:142ee8b12fef 886
nyatla 0:142ee8b12fef 887 //MUTEX LOCK
nyatla 37:fc4b4fd6a649 888 lockResource(i_inst);
nyatla 0:142ee8b12fef 889
nyatla 0:142ee8b12fef 890 //受信バッファを読み出しシーク
nyatla 0:142ee8b12fef 891 NyLPC_cFifoBuffer_pop(&(i_inst->rxbuf),i_seek);
nyatla 0:142ee8b12fef 892 //ACKパケットの生成
nyatla 69:8c5f220441f5 893 setTxPacket(i_inst,buf,TCP_ACK,NULL,0);
nyatla 37:fc4b4fd6a649 894 unlockResource(i_inst);
nyatla 0:142ee8b12fef 895 //ACK送信
nyatla 0:142ee8b12fef 896 NyLPC_cUipService_sendIPv4Tx(buf);
nyatla 0:142ee8b12fef 897 NyLPC_cUipService_releaseTxBuf(buf);
nyatla 69:8c5f220441f5 898
nyatla 0:142ee8b12fef 899 }
nyatla 0:142ee8b12fef 900
nyatla 0:142ee8b12fef 901 /**
nyatla 0:142ee8b12fef 902 * See header file.
nyatla 0:142ee8b12fef 903 */
nyatla 0:142ee8b12fef 904 void* NyLPC_cTcpSocket_allocSendBuf(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_buf_size,NyLPC_TUInt32 i_wait_in_msec)
nyatla 0:142ee8b12fef 905 {
nyatla 0:142ee8b12fef 906 NyLPC_TUInt16 s;
nyatla 0:142ee8b12fef 907 void* buf;
nyatla 0:142ee8b12fef 908 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 909
nyatla 0:142ee8b12fef 910 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 911 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 0:142ee8b12fef 912
nyatla 0:142ee8b12fef 913 //送信バッファを取得
nyatla 20:3b0b444b4deb 914 //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。
nyatla 20:3b0b444b4deb 915 for(;;){
nyatla 37:fc4b4fd6a649 916 //ESTABLISHED以外に非同期遷移
nyatla 37:fc4b4fd6a649 917 if(i_inst->tcpstateflags!=UIP_ESTABLISHED){
nyatla 37:fc4b4fd6a649 918 NyLPC_cStopwatch_finalize(&sw);
nyatla 20:3b0b444b4deb 919 return NULL;
nyatla 20:3b0b444b4deb 920 }
nyatla 20:3b0b444b4deb 921 buf=NyLPC_cUipService_allocTxBuf(i_hint+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
nyatla 20:3b0b444b4deb 922 if(buf!=NULL){
nyatla 20:3b0b444b4deb 923 break;
nyatla 20:3b0b444b4deb 924 }
nyatla 37:fc4b4fd6a649 925 //タイムアウト時もエラー
nyatla 37:fc4b4fd6a649 926 if(NyLPC_cStopwatch_isExpired(&sw)){
nyatla 37:fc4b4fd6a649 927 NyLPC_cStopwatch_finalize(&sw);
nyatla 37:fc4b4fd6a649 928 return NULL;
nyatla 37:fc4b4fd6a649 929 }
nyatla 20:3b0b444b4deb 930 }
nyatla 20:3b0b444b4deb 931
nyatla 37:fc4b4fd6a649 932 //@todo 前段処理と順番を入れ替えて、要求サイズとpeerのwinのうち、小さいほうを割り当てたほうが良くない?
nyatla 37:fc4b4fd6a649 933 //ここで相手のwin待ちをする理由は、相手に確実に受け取れるサイズを決定する為。
nyatla 37:fc4b4fd6a649 934 lockResource(i_inst);
nyatla 0:142ee8b12fef 935 //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
nyatla 0:142ee8b12fef 936 while(i_inst->uip_connr.peer_win==0){
nyatla 37:fc4b4fd6a649 937 unlockResource(i_inst);
nyatla 20:3b0b444b4deb 938 //ESTABLISHED以外に非同期遷移 orタイムアウト確認
nyatla 20:3b0b444b4deb 939 if(NyLPC_cStopwatch_isExpired(&sw)||(i_inst->tcpstateflags!=UIP_ESTABLISHED)){
nyatla 20:3b0b444b4deb 940 NyLPC_cUipService_releaseTxBuf(buf);
nyatla 0:142ee8b12fef 941 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 942 return NULL;
nyatla 0:142ee8b12fef 943 }
nyatla 0:142ee8b12fef 944 NyLPC_cThread_yield();
nyatla 37:fc4b4fd6a649 945 lockResource(i_inst);
nyatla 0:142ee8b12fef 946 }
nyatla 0:142ee8b12fef 947 //送信バッファを基準とした送信サイズを計算
nyatla 0:142ee8b12fef 948 s-=SIZE_OF_IPv4_TCPIP_HEADER;
nyatla 0:142ee8b12fef 949 //送信サイズよりMMSが小さければ、送信サイズを修正
nyatla 0:142ee8b12fef 950 if(i_inst->uip_connr.peer_mss<s){
nyatla 0:142ee8b12fef 951 s=i_inst->uip_connr.peer_mss;
nyatla 0:142ee8b12fef 952 }
nyatla 0:142ee8b12fef 953 //送信サイズよりpeerのウインドウサイズが小さければ修正
nyatla 0:142ee8b12fef 954 if(i_inst->uip_connr.peer_win<s){
nyatla 0:142ee8b12fef 955 s=i_inst->uip_connr.peer_win;
nyatla 0:142ee8b12fef 956 }
nyatla 37:fc4b4fd6a649 957 unlockResource(i_inst);
nyatla 0:142ee8b12fef 958 //バッファサイズ確定。
nyatla 0:142ee8b12fef 959 *o_buf_size=s;
nyatla 0:142ee8b12fef 960 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 961 return (NyLPC_TUInt8*)buf+SIZE_OF_IPv4_TCPIP_HEADER;
nyatla 0:142ee8b12fef 962 }
nyatla 0:142ee8b12fef 963 /**
nyatla 0:142ee8b12fef 964 * See Header file.
nyatla 0:142ee8b12fef 965 */
nyatla 0:142ee8b12fef 966 void NyLPC_cTcpSocket_releaseSendBuf(NyLPC_TcTcpSocket_t* i_inst,void* i_buf_ptr)
nyatla 0:142ee8b12fef 967 {
nyatla 0:142ee8b12fef 968 NyLPC_cUipService_releaseTxBuf((NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER);
nyatla 0:142ee8b12fef 969 }
nyatla 0:142ee8b12fef 970
nyatla 0:142ee8b12fef 971
nyatla 0:142ee8b12fef 972 /**
nyatla 0:142ee8b12fef 973 * 事前にAllocしたTxパケットを送信します。
nyatla 0:142ee8b12fef 974 * このAPIはゼロコピー送信をサポートするためのものです。
nyatla 0:142ee8b12fef 975 * @param i_buf_ptr
nyatla 0:142ee8b12fef 976 * allocSendBufで取得したメモリを指定します。
nyatla 0:142ee8b12fef 977 * @return
nyatla 0:142ee8b12fef 978 * 関数が失敗した場合、i_buf_ptrは「開放されません。」
nyatla 0:142ee8b12fef 979 */
nyatla 0:142ee8b12fef 980 NyLPC_TBool NyLPC_cTcpSocket_psend(NyLPC_TcTcpSocket_t* i_inst,void* i_buf_ptr,int i_len,NyLPC_TUInt32 i_wait_in_msec)
nyatla 0:142ee8b12fef 981 {
nyatla 0:142ee8b12fef 982 struct NyLPC_TcTcpSocket_TxQItem* txq;
nyatla 0:142ee8b12fef 983 void* buf;
nyatla 0:142ee8b12fef 984 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 985 //ESTABLISHEDでなければエラー
nyatla 0:142ee8b12fef 986 if(i_inst->tcpstateflags!=UIP_ESTABLISHED){
nyatla 0:142ee8b12fef 987 //ESTABLISHEDでなければエラー
nyatla 0:142ee8b12fef 988 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 989 }
nyatla 20:3b0b444b4deb 990 //送信データ0なら何もしない。
nyatla 0:142ee8b12fef 991 if(i_len<1){
nyatla 20:3b0b444b4deb 992 NyLPC_cTcpSocket_releaseSendBuf(i_inst,i_buf_ptr);
nyatla 0:142ee8b12fef 993 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 994 }
nyatla 0:142ee8b12fef 995 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 996 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 0:142ee8b12fef 997
nyatla 0:142ee8b12fef 998 //先頭ポインタは、i_buf-sizeof(SIZE_OF_IPv4_TCPIP_HEADER)固定
nyatla 0:142ee8b12fef 999 buf=(NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER;
nyatla 37:fc4b4fd6a649 1000 lockResource(i_inst);
nyatla 0:142ee8b12fef 1001 //送信キューの取得
nyatla 0:142ee8b12fef 1002 txq=getTxQ(i_inst,&sw);
nyatla 0:142ee8b12fef 1003 //送信キューが取れなかった。
nyatla 0:142ee8b12fef 1004 if(txq==NULL){
nyatla 0:142ee8b12fef 1005 //シーケンス番号をロールバックできないので、エラーとする。
nyatla 37:fc4b4fd6a649 1006 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1007 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 1008 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 1009 }
nyatla 0:142ee8b12fef 1010 //ここから先はi_bufの所有権はインスタンスになってる。
nyatla 0:142ee8b12fef 1011
nyatla 0:142ee8b12fef 1012 //IPv4ペイロードの書き込み
nyatla 69:8c5f220441f5 1013
nyatla 0:142ee8b12fef 1014 //allocをした時点でwin,mssは考慮されているので、そのままそうしんしる。
nyatla 69:8c5f220441f5 1015
nyatla 0:142ee8b12fef 1016 //ACK番号の計算
nyatla 0:142ee8b12fef 1017 txq->rto32=i_inst->uip_connr.current_rto32;
nyatla 0:142ee8b12fef 1018 txq->tick_of_sent=NyLPC_cStopwatch_now();
nyatla 69:8c5f220441f5 1019 //パケットヘッダの生成(ヘッダ長はpreadで定義した値(4+6)*4=40です。)
nyatla 69:8c5f220441f5 1020 setTxPacketHeader(i_inst,buf,TCP_ACK|TCP_PSH,i_len);
nyatla 69:8c5f220441f5 1021 txq->packet=buf;
nyatla 69:8c5f220441f5 1022
nyatla 0:142ee8b12fef 1023 //シーケンス番号の更新
nyatla 0:142ee8b12fef 1024 i_inst->uip_connr.snd_nxt32=i_inst->uip_connr.snd_nxt32+i_len;
nyatla 0:142ee8b12fef 1025 //Peerのウインドウサイズを更新
nyatla 0:142ee8b12fef 1026 i_inst->uip_connr.peer_win-=i_len;
nyatla 0:142ee8b12fef 1027 //ACK番号の返却
nyatla 0:142ee8b12fef 1028 txq->ackno=NyLPC_HTONL(i_inst->uip_connr.snd_nxt32);
nyatla 37:fc4b4fd6a649 1029 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1030 NyLPC_cUipService_sendIPv4Tx(buf);
nyatla 0:142ee8b12fef 1031 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 1032 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 1033 }
nyatla 0:142ee8b12fef 1034
nyatla 0:142ee8b12fef 1035 /**
nyatla 0:142ee8b12fef 1036 * See header file.
nyatla 0:142ee8b12fef 1037 */
nyatla 20:3b0b444b4deb 1038 NyLPC_TInt32 NyLPC_cTcpSocket_send(NyLPC_TcTcpSocket_t* i_inst,const void* i_buf_ptr,NyLPC_TInt32 i_len,NyLPC_TUInt32 i_wait_in_msec)
nyatla 0:142ee8b12fef 1039 {
nyatla 20:3b0b444b4deb 1040 NyLPC_TInt16 hint;
nyatla 20:3b0b444b4deb 1041 NyLPC_TUInt16 s;
nyatla 20:3b0b444b4deb 1042 void* buf;
nyatla 0:142ee8b12fef 1043 if(i_len<1){
nyatla 0:142ee8b12fef 1044 return 0;
nyatla 0:142ee8b12fef 1045 }
nyatla 57:bc4330dfa62f 1046 hint=(i_len>32767)?32767:i_len;
nyatla 20:3b0b444b4deb 1047 buf=NyLPC_cTcpSocket_allocSendBuf(i_inst,hint,&s,i_wait_in_msec);
nyatla 20:3b0b444b4deb 1048 if(buf==NULL){
nyatla 20:3b0b444b4deb 1049 return -1;
nyatla 20:3b0b444b4deb 1050 }
nyatla 20:3b0b444b4deb 1051 //送信サイズの計算
nyatla 20:3b0b444b4deb 1052 s=((NyLPC_TInt32)s<i_len)?s:(NyLPC_TUInt16)i_len;
nyatla 20:3b0b444b4deb 1053 memcpy(buf,i_buf_ptr,s);
nyatla 20:3b0b444b4deb 1054 if(!NyLPC_cTcpSocket_psend(i_inst,buf,s,i_wait_in_msec)){
nyatla 20:3b0b444b4deb 1055 NyLPC_cTcpSocket_releaseSendBuf(i_inst,buf);
nyatla 37:fc4b4fd6a649 1056 return -1;//error
nyatla 20:3b0b444b4deb 1057 }
nyatla 20:3b0b444b4deb 1058 return s;
nyatla 0:142ee8b12fef 1059 }
nyatla 0:142ee8b12fef 1060
nyatla 0:142ee8b12fef 1061
nyatla 0:142ee8b12fef 1062 void NyLPC_cTcpSocket_close(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
nyatla 0:142ee8b12fef 1063 {
nyatla 0:142ee8b12fef 1064 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 1065 volatile NyLPC_TUInt8 f;
nyatla 0:142ee8b12fef 1066 NyLPC_TUInt32 sq;
nyatla 0:142ee8b12fef 1067 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 1068 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 37:fc4b4fd6a649 1069 lockResource(i_inst);
nyatla 0:142ee8b12fef 1070
nyatla 0:142ee8b12fef 1071 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 1072 //ステータスチェック
nyatla 0:142ee8b12fef 1073 switch(f)
nyatla 0:142ee8b12fef 1074 {
nyatla 0:142ee8b12fef 1075 case UIP_CLOSED:
nyatla 0:142ee8b12fef 1076 //閉じている。
nyatla 0:142ee8b12fef 1077 goto ReturnWithUnlock;
nyatla 0:142ee8b12fef 1078 case UIP_ESTABLISHED:
nyatla 0:142ee8b12fef 1079 //アクティブクローズ。
nyatla 0:142ee8b12fef 1080 i_inst->tcpstateflags=UIP_FIN_WAIT_1;
nyatla 0:142ee8b12fef 1081 //送信のために一旦解除
nyatla 37:fc4b4fd6a649 1082 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1083 //FINの送信
nyatla 0:142ee8b12fef 1084 if(sendWithRetransmit(i_inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
nyatla 0:142ee8b12fef 1085 //ちょっと待つ。
nyatla 0:142ee8b12fef 1086 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 1087 //TXの消去待ち
nyatla 0:142ee8b12fef 1088 if(waitForTxRemove(i_inst,sq,&sw)){
nyatla 0:142ee8b12fef 1089 //再ロック
nyatla 37:fc4b4fd6a649 1090 lockResource(i_inst);
nyatla 0:142ee8b12fef 1091 //タイムアウトするか、UIP_CLOSED、もしくはTIME_WAITに遷移するのを待つ。(遷移はRxprocで自動的に実行。)
nyatla 58:03b89038b21a 1092 do{
nyatla 0:142ee8b12fef 1093 switch(i_inst->tcpstateflags)
nyatla 0:142ee8b12fef 1094 {
nyatla 0:142ee8b12fef 1095 case UIP_TIME_WAIT:
nyatla 0:142ee8b12fef 1096 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 0:142ee8b12fef 1097 case UIP_CLOSED:
nyatla 0:142ee8b12fef 1098 NyLPC_Assert(i_inst->txbuf.rp==i_inst->txbuf.wp);
nyatla 0:142ee8b12fef 1099 //成功。
nyatla 0:142ee8b12fef 1100 goto ReturnWithUnlock;
nyatla 0:142ee8b12fef 1101 case UIP_FIN_WAIT_1:
nyatla 0:142ee8b12fef 1102 case UIP_FIN_WAIT_2:
nyatla 0:142ee8b12fef 1103 case UIP_CLOSING:
nyatla 0:142ee8b12fef 1104 //一時的なアンロック
nyatla 37:fc4b4fd6a649 1105 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1106 NyLPC_cThread_yield();
nyatla 37:fc4b4fd6a649 1107 lockResource(i_inst);
nyatla 0:142ee8b12fef 1108 default:
nyatla 0:142ee8b12fef 1109 break;
nyatla 0:142ee8b12fef 1110 }
nyatla 58:03b89038b21a 1111 }while(!NyLPC_cStopwatch_isExpired(&sw));
nyatla 37:fc4b4fd6a649 1112 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1113 }
nyatla 0:142ee8b12fef 1114 }
nyatla 0:142ee8b12fef 1115 break;
nyatla 0:142ee8b12fef 1116 case UIP_CLOSE_WAIT:
nyatla 0:142ee8b12fef 1117 //LAST_ACKへ遷移
nyatla 0:142ee8b12fef 1118 i_inst->tcpstateflags=UIP_LAST_ACK;
nyatla 0:142ee8b12fef 1119 //送信のために一旦解除
nyatla 37:fc4b4fd6a649 1120 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1121 if(sendWithRetransmit(i_inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
nyatla 0:142ee8b12fef 1122 //ちょっと待つ。
nyatla 0:142ee8b12fef 1123 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 1124 //TXの消去待ち
nyatla 0:142ee8b12fef 1125 if(waitForTxRemove(i_inst,sq,&sw)){
nyatla 0:142ee8b12fef 1126 //再ロック
nyatla 37:fc4b4fd6a649 1127 lockResource(i_inst);
nyatla 0:142ee8b12fef 1128 //TX消去後にCLOSEDに遷移していればOK
nyatla 0:142ee8b12fef 1129 if(i_inst->tcpstateflags==UIP_CLOSED)
nyatla 0:142ee8b12fef 1130 {
nyatla 0:142ee8b12fef 1131 NyLPC_Assert(i_inst->txbuf.rp==i_inst->txbuf.wp);
nyatla 0:142ee8b12fef 1132 goto ReturnWithUnlock;
nyatla 0:142ee8b12fef 1133 }
nyatla 37:fc4b4fd6a649 1134 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1135 }
nyatla 0:142ee8b12fef 1136 }
nyatla 0:142ee8b12fef 1137 //エラー。RSTで切断。
nyatla 0:142ee8b12fef 1138 break;
nyatla 0:142ee8b12fef 1139 default:
nyatla 37:fc4b4fd6a649 1140 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1141 NyLPC_Warning();
nyatla 0:142ee8b12fef 1142 break;
nyatla 0:142ee8b12fef 1143 }
nyatla 37:fc4b4fd6a649 1144 // if(i_inst->_smutex._lock_count>0){
nyatla 37:fc4b4fd6a649 1145 // NyLPC_Warning();
nyatla 37:fc4b4fd6a649 1146 // }
nyatla 0:142ee8b12fef 1147 //このパスに到達するのは、FIN送信/ACKに成功したにも拘らず、規定時間内にCLOSEDに遷移しなかった場合。
nyatla 0:142ee8b12fef 1148 //コネクションを強制遷移して、RST
nyatla 37:fc4b4fd6a649 1149 lockResource(i_inst);
nyatla 0:142ee8b12fef 1150 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 1151 if(f!=UIP_CLOSED){
nyatla 57:bc4330dfa62f 1152 //もし、強制CLOSE遷移であれば、RSTも送信。
nyatla 0:142ee8b12fef 1153 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 57:bc4330dfa62f 1154 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1155 sendRst(i_inst);
nyatla 57:bc4330dfa62f 1156 }else{
nyatla 57:bc4330dfa62f 1157 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1158 }
nyatla 0:142ee8b12fef 1159 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 1160 return;
nyatla 0:142ee8b12fef 1161 ReturnWithUnlock:
nyatla 37:fc4b4fd6a649 1162 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1163 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 1164 return;
nyatla 0:142ee8b12fef 1165 }
nyatla 0:142ee8b12fef 1166
nyatla 0:142ee8b12fef 1167 /**
nyatla 37:fc4b4fd6a649 1168 * uipサービスタスクが実行する関数です。
nyatla 0:142ee8b12fef 1169 * 定期的に実行する関数。最低でも1s単位で実行してください。
nyatla 0:142ee8b12fef 1170 */
nyatla 0:142ee8b12fef 1171 void NyLPC_cTcpSocket_periodic(
nyatla 0:142ee8b12fef 1172 NyLPC_TcTcpSocket_t* i_inst)
nyatla 0:142ee8b12fef 1173 {
nyatla 0:142ee8b12fef 1174 int i;
nyatla 0:142ee8b12fef 1175 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 1176 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 1177 NyLPC_TUInt32 now;
nyatla 0:142ee8b12fef 1178 int rp;
nyatla 0:142ee8b12fef 1179 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 1180 now=NyLPC_cStopwatch_now();
nyatla 0:142ee8b12fef 1181 //MUTEX LOCK
nyatla 37:fc4b4fd6a649 1182 lockResource(i_inst);
nyatla 0:142ee8b12fef 1183 if(i_inst->tcpstateflags==UIP_CLOSED)
nyatla 0:142ee8b12fef 1184 {
nyatla 0:142ee8b12fef 1185 //CLOSEDなら、バッファ開放。
nyatla 0:142ee8b12fef 1186 resetTxQWithUnlock(i_inst);
nyatla 0:142ee8b12fef 1187 }else if(i_inst->txbuf.rp==i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 1188 //再送信パケットがなければ何もしないよ。
nyatla 37:fc4b4fd6a649 1189 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1190 }else if(i_inst->uip_connr.peer_win==0){
nyatla 0:142ee8b12fef 1191 //peer_winが0の場合は何もしない。
nyatla 37:fc4b4fd6a649 1192 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1193 }else{
nyatla 0:142ee8b12fef 1194 //再送信処理
nyatla 0:142ee8b12fef 1195 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 1196 NyLPC_cStopwatch_set(&sw,q[rp].tick_of_sent);
nyatla 0:142ee8b12fef 1197 if(NyLPC_cStopwatch_elapseInMsec(&sw)>q[rp].rto32){
nyatla 0:142ee8b12fef 1198 //最古のパケットの送信時間をチェックして、タイムアウトが発生したら、再送時間と送信時刻をセット
nyatla 0:142ee8b12fef 1199 //最古パケットRTOを2倍。
nyatla 0:142ee8b12fef 1200 q[rp].rto32*=2;
nyatla 0:142ee8b12fef 1201 for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
nyatla 0:142ee8b12fef 1202 q[i].tick_of_sent=now;
nyatla 0:142ee8b12fef 1203 }
nyatla 0:142ee8b12fef 1204 if(q[rp].rto32>UIP_IP_RTO_MAX_RTO){
nyatla 0:142ee8b12fef 1205 //最古のRTOが64秒を超えたら、CLOSED
nyatla 0:142ee8b12fef 1206 i_inst->tcpstateflags =UIP_CLOSED;
nyatla 0:142ee8b12fef 1207 resetTxQWithUnlock(i_inst);
nyatla 0:142ee8b12fef 1208 sendRst(i_inst);
nyatla 0:142ee8b12fef 1209 }else{
nyatla 0:142ee8b12fef 1210 //規定時間内なら、再送処理
nyatla 0:142ee8b12fef 1211 for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
nyatla 69:8c5f220441f5 1212 // NyLPC_cUipService_sendIPv4Tx(NyLPC_cIPv4Payload_getBuf(&(q[i].data)));
nyatla 69:8c5f220441f5 1213 NyLPC_cUipService_sendIPv4Tx(q[i].packet);
nyatla 0:142ee8b12fef 1214 }
nyatla 37:fc4b4fd6a649 1215 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1216 }
nyatla 0:142ee8b12fef 1217 }else{
nyatla 37:fc4b4fd6a649 1218 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1219 }
nyatla 0:142ee8b12fef 1220 }
nyatla 0:142ee8b12fef 1221 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 1222 return;
nyatla 0:142ee8b12fef 1223 }
nyatla 37:fc4b4fd6a649 1224 /**
nyatla 37:fc4b4fd6a649 1225 * uipサービスタスクが実行する関数です。
nyatla 37:fc4b4fd6a649 1226 * サービスの開始を通知します。
nyatla 37:fc4b4fd6a649 1227 */
nyatla 37:fc4b4fd6a649 1228 void NyLPC_cTcpSocket_startService(NyLPC_TcTcpSocket_t* i_inst,const NyLPC_TcIPv4Config_t* i_config)
nyatla 37:fc4b4fd6a649 1229 {
nyatla 37:fc4b4fd6a649 1230 NyLPC_Assert(i_inst->tcpstateflags==UIP_CLOSED);//閉じてなければおかしい。
nyatla 43:a182f2b5ff41 1231 i_inst->uip_connr.lipaddr=&(i_config->ip_addr);
nyatla 37:fc4b4fd6a649 1232 i_inst->uip_connr.default_mss=i_config->default_mss;
nyatla 37:fc4b4fd6a649 1233 //NyLPC_cTcpSocket_setSynPayload関数でも実行するけど、IFのリセット時なのでここでもやる。
nyatla 37:fc4b4fd6a649 1234 NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
nyatla 37:fc4b4fd6a649 1235 return;
nyatla 37:fc4b4fd6a649 1236 }
nyatla 37:fc4b4fd6a649 1237 /**
nyatla 37:fc4b4fd6a649 1238 * uipサービスタスクが実行する関数です。
nyatla 37:fc4b4fd6a649 1239 * サービスの停止を通知します。
nyatla 37:fc4b4fd6a649 1240 */
nyatla 37:fc4b4fd6a649 1241 void NyLPC_cTcpSocket_stopService(NyLPC_TcTcpSocket_t* i_inst)
nyatla 37:fc4b4fd6a649 1242 {
nyatla 37:fc4b4fd6a649 1243 lockResource(i_inst);
nyatla 37:fc4b4fd6a649 1244 if(i_inst->tcpstateflags==UIP_CLOSED)
nyatla 37:fc4b4fd6a649 1245 {
nyatla 37:fc4b4fd6a649 1246 unlockResource(i_inst);
nyatla 37:fc4b4fd6a649 1247 }else{
nyatla 37:fc4b4fd6a649 1248 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 37:fc4b4fd6a649 1249 resetTxQWithUnlock(i_inst);
nyatla 37:fc4b4fd6a649 1250 sendRst(i_inst);
nyatla 37:fc4b4fd6a649 1251 }
nyatla 37:fc4b4fd6a649 1252 return;
nyatla 37:fc4b4fd6a649 1253 }
nyatla 0:142ee8b12fef 1254
nyatla 69:8c5f220441f5 1255
nyatla 69:8c5f220441f5 1256 void* NyLPC_cTcpSocket_parseRx(
nyatla 0:142ee8b12fef 1257 NyLPC_TcTcpSocket_t* i_inst,
nyatla 69:8c5f220441f5 1258 const NyLPC_TcIPv4Payload_t* i_ipp)
nyatla 0:142ee8b12fef 1259 {
nyatla 0:142ee8b12fef 1260 int i,s;
nyatla 0:142ee8b12fef 1261 NyLPC_TUInt16 tmp16;
nyatla 0:142ee8b12fef 1262 NyLPC_TUInt16 data_size;
nyatla 69:8c5f220441f5 1263 NyLPC_TUInt8 in_tcpflag=i_ipp->payload.tcp->flags;
nyatla 69:8c5f220441f5 1264 const void* tcp_data_offset;
nyatla 0:142ee8b12fef 1265 NyLPC_TBool is_new_packet;
nyatla 0:142ee8b12fef 1266 int num_of_noack;
nyatla 0:142ee8b12fef 1267 void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
nyatla 69:8c5f220441f5 1268 void* ret;
nyatla 0:142ee8b12fef 1269
nyatla 0:142ee8b12fef 1270 //パラメータの計算
nyatla 0:142ee8b12fef 1271
nyatla 69:8c5f220441f5 1272 tmp16=NyLPC_TTcpHeader_getHeaderLength(i_ipp->payload.tcp);
nyatla 0:142ee8b12fef 1273 //TCPペイロードの長さは、IPパケットの長さ-(IPヘッダ+TCPヘッダ)
nyatla 69:8c5f220441f5 1274 data_size=NyLPC_TIPv4Header_getPacketLength(i_ipp->header)-NyLPC_TIPv4Header_getHeaderLength(i_ipp->header)-tmp16;
nyatla 0:142ee8b12fef 1275 //TCPデータオフセット
nyatla 69:8c5f220441f5 1276 tcp_data_offset=i_ipp->payload.rawbuf+tmp16;
nyatla 0:142ee8b12fef 1277
nyatla 0:142ee8b12fef 1278 //インスタンスをロックする。
nyatla 37:fc4b4fd6a649 1279 lockResource(i_inst);
nyatla 0:142ee8b12fef 1280
nyatla 0:142ee8b12fef 1281 //RSTのチェック。RST受信時は、状態にかかわらず、CLOSEDステータスに移行する。
nyatla 0:142ee8b12fef 1282 if (in_tcpflag & TCP_RST)
nyatla 0:142ee8b12fef 1283 {
nyatla 0:142ee8b12fef 1284 i_inst->tcpstateflags =UIP_CLOSED;
nyatla 0:142ee8b12fef 1285 goto DROP;
nyatla 0:142ee8b12fef 1286 }
nyatla 0:142ee8b12fef 1287
nyatla 0:142ee8b12fef 1288
nyatla 69:8c5f220441f5 1289 is_new_packet=NyLPC_ntohl(i_ipp->payload.tcp->seqno32)==i_inst->uip_connr.rcv_nxt32;
nyatla 0:142ee8b12fef 1290
nyatla 0:142ee8b12fef 1291
nyatla 0:142ee8b12fef 1292 //OPTIONの反映
nyatla 0:142ee8b12fef 1293
nyatla 0:142ee8b12fef 1294 //MSSの取得
nyatla 69:8c5f220441f5 1295 if(NyLPC_TTcpHeader_getTcpMmsOpt(i_ipp->payload.tcp,&tmp16)){
nyatla 0:142ee8b12fef 1296 //取得で着たら更新
nyatla 0:142ee8b12fef 1297 i_inst->uip_connr.peer_mss=tmp16;
nyatla 0:142ee8b12fef 1298 }
nyatla 0:142ee8b12fef 1299 //受信パケットを元に、未ACKパケットの数を計算
nyatla 69:8c5f220441f5 1300 num_of_noack=getNumOfSending(i_inst,i_ipp->payload.tcp->ackno32);//i_inst->txbuf.num_of_txq;
nyatla 0:142ee8b12fef 1301
nyatla 0:142ee8b12fef 1302 //ステータス毎のACK応答
nyatla 0:142ee8b12fef 1303 switch(i_inst->tcpstateflags)
nyatla 0:142ee8b12fef 1304 {
nyatla 0:142ee8b12fef 1305 case UIP_SYN_RCVD:
nyatla 0:142ee8b12fef 1306 //ACKを受信したら、ESTABLISHEDへ。
nyatla 0:142ee8b12fef 1307 //すべてのパケットをACKしたかで判定。()
nyatla 0:142ee8b12fef 1308 if(num_of_noack==0){
nyatla 0:142ee8b12fef 1309 i_inst->tcpstateflags=UIP_ESTABLISHED;
nyatla 0:142ee8b12fef 1310 }else{
nyatla 0:142ee8b12fef 1311 //それ以外のパケットはドロップする。
nyatla 0:142ee8b12fef 1312 break;//goto DROP;
nyatla 0:142ee8b12fef 1313 }
nyatla 0:142ee8b12fef 1314 //新しいパケットがなければ、無応答
nyatla 0:142ee8b12fef 1315 if(!is_new_packet){
nyatla 0:142ee8b12fef 1316 break;//goto DROP;
nyatla 0:142ee8b12fef 1317 }
nyatla 0:142ee8b12fef 1318 //引き続き、ESTABLISHEDの処理へ。
nyatla 0:142ee8b12fef 1319 case UIP_ESTABLISHED:
nyatla 0:142ee8b12fef 1320 if(data_size>0){
nyatla 0:142ee8b12fef 1321 if(is_new_packet){
nyatla 0:142ee8b12fef 1322 if(addRecvData(i_inst,tcp_data_offset,data_size)){
nyatla 0:142ee8b12fef 1323 //通常のACK返却
nyatla 0:142ee8b12fef 1324 i_inst->uip_connr.rcv_nxt32+=data_size;
nyatla 0:142ee8b12fef 1325 }else{
nyatla 0:142ee8b12fef 1326 //失敗したときは必要に応じて単純ACK
nyatla 0:142ee8b12fef 1327 }
nyatla 0:142ee8b12fef 1328 }
nyatla 0:142ee8b12fef 1329 }
nyatla 0:142ee8b12fef 1330 //どちらにしろ、ACK送信
nyatla 0:142ee8b12fef 1331 if(is_new_packet && (in_tcpflag & TCP_FIN)){
nyatla 0:142ee8b12fef 1332 //FINがあるときは、ステータスをCLOSE_WAITへセットして、ACKを返す。
nyatla 0:142ee8b12fef 1333 i_inst->tcpstateflags = UIP_CLOSE_WAIT;
nyatla 0:142ee8b12fef 1334 i_inst->uip_connr.rcv_nxt32++;
nyatla 0:142ee8b12fef 1335 }
nyatla 0:142ee8b12fef 1336 break;
nyatla 0:142ee8b12fef 1337 case UIP_CLOSE_WAIT:
nyatla 0:142ee8b12fef 1338 //必要に応じたACK応答
nyatla 0:142ee8b12fef 1339 break;
nyatla 0:142ee8b12fef 1340 case UIP_LAST_ACK:
nyatla 0:142ee8b12fef 1341 //ACK(by FIN)が得られたなら、CLOSEDへ。
nyatla 0:142ee8b12fef 1342 if(num_of_noack==0){
nyatla 0:142ee8b12fef 1343 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 0:142ee8b12fef 1344 }
nyatla 0:142ee8b12fef 1345 //必要に応じたACK応答
nyatla 0:142ee8b12fef 1346 break;
nyatla 0:142ee8b12fef 1347 case UIP_FIN_WAIT_1:
nyatla 0:142ee8b12fef 1348 //FIN受信->CLOSINGへ
nyatla 63:157ee3202edb 1349 if(is_new_packet){
nyatla 63:157ee3202edb 1350 i_inst->uip_connr.rcv_nxt32+=data_size;
nyatla 63:157ee3202edb 1351 if(in_tcpflag & TCP_FIN){
nyatla 63:157ee3202edb 1352 i_inst->uip_connr.rcv_nxt32++;
nyatla 63:157ee3202edb 1353 if(num_of_noack==0){
nyatla 63:157ee3202edb 1354 //FINとACKを受信
nyatla 63:157ee3202edb 1355 i_inst->tcpstateflags=UIP_TIME_WAIT;
nyatla 63:157ee3202edb 1356 }else{
nyatla 63:157ee3202edb 1357 //FINのみ
nyatla 63:157ee3202edb 1358 i_inst->tcpstateflags=UIP_CLOSING;
nyatla 63:157ee3202edb 1359 }
nyatla 0:142ee8b12fef 1360 }
nyatla 0:142ee8b12fef 1361 }else if(num_of_noack==0){
nyatla 0:142ee8b12fef 1362 //ACKのみ
nyatla 0:142ee8b12fef 1363 i_inst->tcpstateflags=UIP_FIN_WAIT_2;
nyatla 0:142ee8b12fef 1364 }
nyatla 0:142ee8b12fef 1365 //必要に応じたACK応答
nyatla 0:142ee8b12fef 1366 break;
nyatla 0:142ee8b12fef 1367 case UIP_FIN_WAIT_2:
nyatla 0:142ee8b12fef 1368 //FIN受信->TIME_WAITへ(pureACK)
nyatla 0:142ee8b12fef 1369 if(is_new_packet && (in_tcpflag & TCP_FIN)){
nyatla 0:142ee8b12fef 1370 i_inst->uip_connr.rcv_nxt32++;
nyatla 0:142ee8b12fef 1371 i_inst->tcpstateflags=UIP_TIME_WAIT;
nyatla 0:142ee8b12fef 1372 }
nyatla 0:142ee8b12fef 1373 break;
nyatla 0:142ee8b12fef 1374 case UIP_CLOSING:
nyatla 0:142ee8b12fef 1375 //ACK受信したら、TIME_WAITへ
nyatla 0:142ee8b12fef 1376 if(num_of_noack==0){
nyatla 0:142ee8b12fef 1377 i_inst->tcpstateflags=UIP_TIME_WAIT;
nyatla 0:142ee8b12fef 1378 }
nyatla 0:142ee8b12fef 1379 break;
nyatla 0:142ee8b12fef 1380 case UIP_CLOSED:
nyatla 0:142ee8b12fef 1381 //何もできない。何もしない。
nyatla 57:bc4330dfa62f 1382 break;
nyatla 0:142ee8b12fef 1383 case UIP_TIME_WAIT:
nyatla 0:142ee8b12fef 1384 //最終ACKを送り続ける。
nyatla 0:142ee8b12fef 1385 break;
nyatla 57:bc4330dfa62f 1386 case UIP_SYN_SENT:
nyatla 57:bc4330dfa62f 1387 //connect関数実行中しか起動しないステータス
nyatla 57:bc4330dfa62f 1388 if(num_of_noack==0){
nyatla 57:bc4330dfa62f 1389 i_inst->tcpstateflags=UIP_ESTABLISHED;
nyatla 69:8c5f220441f5 1390 i_inst->uip_connr.rcv_nxt32=NyLPC_ntohl(i_ipp->payload.tcp->seqno32)+1;
nyatla 57:bc4330dfa62f 1391 }else{
nyatla 57:bc4330dfa62f 1392 //それ以外のパケットはドロップする。
nyatla 57:bc4330dfa62f 1393 break;//goto DROP;
nyatla 57:bc4330dfa62f 1394 }
nyatla 57:bc4330dfa62f 1395 //ACKを送る。
nyatla 57:bc4330dfa62f 1396 break;
nyatla 0:142ee8b12fef 1397 default:
nyatla 0:142ee8b12fef 1398 goto DROP;
nyatla 0:142ee8b12fef 1399 }
nyatla 0:142ee8b12fef 1400 //ウインドウサイズを更新
nyatla 69:8c5f220441f5 1401 i_inst->uip_connr.peer_win=NyLPC_ntohs(i_ipp->payload.tcp->wnd16);
nyatla 0:142ee8b12fef 1402
nyatla 0:142ee8b12fef 1403 //送信キューから、Peerが受信したデータを削除する。
nyatla 0:142ee8b12fef 1404 if(in_tcpflag & TCP_ACK){
nyatla 0:142ee8b12fef 1405 //再送パケットキューから送信済みのデータを回収(後で開放)
nyatla 0:142ee8b12fef 1406 NyLPC_Trace();
nyatla 69:8c5f220441f5 1407 s=updateTxQByIndex(i_inst,i_ipp->payload.tcp->ackno32,dlist);
nyatla 0:142ee8b12fef 1408 NyLPC_Trace();
nyatla 0:142ee8b12fef 1409 }else{
nyatla 0:142ee8b12fef 1410 s=0;
nyatla 0:142ee8b12fef 1411 }
nyatla 0:142ee8b12fef 1412 //新しいパケットがきた場合は、再送キューのACKを更新する。
nyatla 0:142ee8b12fef 1413 if(is_new_packet){
nyatla 0:142ee8b12fef 1414 //再送キューのACKを更新
nyatla 0:142ee8b12fef 1415 updateTxAck(i_inst,NyLPC_htonl(i_inst->uip_connr.rcv_nxt32));
nyatla 0:142ee8b12fef 1416 }
nyatla 0:142ee8b12fef 1417
nyatla 0:142ee8b12fef 1418 //送信キューのない
nyatla 0:142ee8b12fef 1419 if(((in_tcpflag&(TCP_FIN|TCP_SYN))!=0x00) ||
nyatla 0:142ee8b12fef 1420 ((!is_new_packet) && (data_size>0)))
nyatla 0:142ee8b12fef 1421 {
nyatla 69:8c5f220441f5 1422 //ソケットからPureACKを生成 as setPacket(i_inst,i_ipp,TCP_ACK,NULL,0);
nyatla 69:8c5f220441f5 1423 ret=NyLPC_cUipService_allocSysTxBuf();
nyatla 69:8c5f220441f5 1424 setTxPacket(i_inst,ret,TCP_ACK,NULL,0);
nyatla 0:142ee8b12fef 1425 }else{
nyatla 69:8c5f220441f5 1426 ret=NULL;
nyatla 0:142ee8b12fef 1427 }
nyatla 37:fc4b4fd6a649 1428 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1429 //取り外したTXメモリの開放
nyatla 0:142ee8b12fef 1430 for(i=0;i<s;i++){
nyatla 0:142ee8b12fef 1431 //取り外したTXメモリを開放
nyatla 0:142ee8b12fef 1432 NyLPC_cUipService_releaseTxBuf(dlist[i]);
nyatla 0:142ee8b12fef 1433 }
nyatla 0:142ee8b12fef 1434 NyLPC_Trace();
nyatla 0:142ee8b12fef 1435 return ret;
nyatla 0:142ee8b12fef 1436 DROP:
nyatla 0:142ee8b12fef 1437 //ACKしたパケットを送信キューから削除
nyatla 37:fc4b4fd6a649 1438 unlockResource(i_inst);
nyatla 0:142ee8b12fef 1439 NyLPC_Trace();
nyatla 69:8c5f220441f5 1440 return NULL;
nyatla 69:8c5f220441f5 1441 }
nyatla 69:8c5f220441f5 1442
nyatla 69:8c5f220441f5 1443
nyatla 69:8c5f220441f5 1444 /**
nyatla 69:8c5f220441f5 1445 * 入力されたパケットからRSTパケットを生成して返す。
nyatla 69:8c5f220441f5 1446 */
nyatla 69:8c5f220441f5 1447 void* NyLPC_cTcpSocket_allocTcpReverseRstAck(
nyatla 69:8c5f220441f5 1448 const NyLPC_TcIPv4Payload_t* i_src)
nyatla 69:8c5f220441f5 1449 {
nyatla 69:8c5f220441f5 1450 struct NyLPC_TIPv4Header* iph;
nyatla 69:8c5f220441f5 1451 struct NyLPC_TTcpHeader* tcph;
nyatla 69:8c5f220441f5 1452 NyLPC_TUInt8 iph_word=0x05;
nyatla 69:8c5f220441f5 1453 NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
nyatla 69:8c5f220441f5 1454 void* txb=NyLPC_cUipService_allocSysTxBuf();
nyatla 69:8c5f220441f5 1455 //IPヘッダの更新
nyatla 69:8c5f220441f5 1456 iph=(struct NyLPC_TIPv4Header*)txb;
nyatla 69:8c5f220441f5 1457 iph->vhl=0x40|(0x0f&iph_word);
nyatla 69:8c5f220441f5 1458 iph->destipaddr=i_src->header->srcipaddr;
nyatla 69:8c5f220441f5 1459 iph->srcipaddr =i_src->header->destipaddr;
nyatla 69:8c5f220441f5 1460 NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
nyatla 69:8c5f220441f5 1461
nyatla 69:8c5f220441f5 1462 //TCPヘッダの更新
nyatla 69:8c5f220441f5 1463 tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)txb)+NyLPC_TIPv4Header_getHeaderLength(iph));
nyatla 69:8c5f220441f5 1464
nyatla 69:8c5f220441f5 1465 tcph->tcpoffset=(tcph_word<<4);
nyatla 69:8c5f220441f5 1466
nyatla 69:8c5f220441f5 1467 tcph->flags = TCP_RST | TCP_ACK;
nyatla 69:8c5f220441f5 1468 //sorce & destination port
nyatla 69:8c5f220441f5 1469 tcph->srcport = i_src->payload.tcp->destport;
nyatla 69:8c5f220441f5 1470 tcph->destport = i_src->payload.tcp->srcport;
nyatla 69:8c5f220441f5 1471 //ACK number
nyatla 69:8c5f220441f5 1472 tcph->ackno32 = NyLPC_htonl(NyLPC_ntohl(i_src->payload.tcp->seqno32)+1);
nyatla 69:8c5f220441f5 1473 //Seq Number
nyatla 69:8c5f220441f5 1474 tcph->seqno32 = i_src->payload.tcp->ackno32;
nyatla 69:8c5f220441f5 1475 //uip_func_tcp_send_noconn(BUF);
nyatla 69:8c5f220441f5 1476 tcph->urgp[0] = tcph->urgp[1] = 0;
nyatla 69:8c5f220441f5 1477 tcph->tcpchksum= 0;
nyatla 69:8c5f220441f5 1478
nyatla 69:8c5f220441f5 1479
nyatla 69:8c5f220441f5 1480 //最終的なパケットサイズと必要ならペイロードを書き込み
nyatla 69:8c5f220441f5 1481 iph->len16=NyLPC_htons((iph_word+tcph_word)*4);
nyatla 69:8c5f220441f5 1482 //WND設定
nyatla 69:8c5f220441f5 1483 tcph->wnd16=0;
nyatla 69:8c5f220441f5 1484 //Checksumの生成
nyatla 69:8c5f220441f5 1485 tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
nyatla 69:8c5f220441f5 1486 iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
nyatla 69:8c5f220441f5 1487 return txb;
nyatla 0:142ee8b12fef 1488 }
nyatla 0:142ee8b12fef 1489
nyatla 20:3b0b444b4deb 1490
nyatla 20:3b0b444b4deb 1491
nyatla 20:3b0b444b4deb 1492