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:
Wed Jan 30 03:46:05 2013 +0000
Revision:
0:142ee8b12fef
ported core classes

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 0:142ee8b12fef 34
nyatla 0:142ee8b12fef 35 /**
nyatla 0:142ee8b12fef 36 * for Debug
nyatla 0:142ee8b12fef 37 * RTOの情報をログ領域に取る。
nyatla 0:142ee8b12fef 38 */
nyatla 0:142ee8b12fef 39 #ifdef RTO_LOG
nyatla 0:142ee8b12fef 40 NyLPC_TUInt32 rto_log[256];
nyatla 0:142ee8b12fef 41 int rto_log_st=0;
nyatla 0:142ee8b12fef 42 #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 43 #else
nyatla 0:142ee8b12fef 44 #define DEBUG_RTO_LOG(i_inst)
nyatla 0:142ee8b12fef 45 #endif
nyatla 0:142ee8b12fef 46
nyatla 0:142ee8b12fef 47 static void sendRst(NyLPC_TcTcpSocket_t* i_inst);
nyatla 0:142ee8b12fef 48
nyatla 0:142ee8b12fef 49
nyatla 0:142ee8b12fef 50 /**
nyatla 0:142ee8b12fef 51 * ソケットステータスを元に、IPパケットを構成します。
nyatla 0:142ee8b12fef 52 * この関数は、ロック状態でコールしてください。
nyatla 0:142ee8b12fef 53 */
nyatla 0:142ee8b12fef 54 static void setPacket(const NyLPC_TcTcpSocket_t* i_inst,NyLPC_TcIPv4Payload_t* i_payload,NyLPC_TUInt8 i_tcpf,const void* i_buf,NyLPC_TUInt16 i_len)
nyatla 0:142ee8b12fef 55 {
nyatla 0:142ee8b12fef 56 void* buf;
nyatla 0:142ee8b12fef 57 switch(i_tcpf){
nyatla 0:142ee8b12fef 58 case TCP_PSH|TCP_ACK:
nyatla 0:142ee8b12fef 59 buf=NyLPC_cIPv4Payload_initTcpTx(i_payload,0x05,((UIP_TCPH_LEN) / 4),i_len);
nyatla 0:142ee8b12fef 60 NyLPC_cIPv4Payload_setTcpTxHeaderByConnection(i_payload,&(i_inst->uip_connr),TCP_ACK|TCP_PSH);
nyatla 0:142ee8b12fef 61 //bufの書き込み
nyatla 0:142ee8b12fef 62 memcpy(buf,i_buf,i_len);
nyatla 0:142ee8b12fef 63 break;
nyatla 0:142ee8b12fef 64 case TCP_ACK:
nyatla 0:142ee8b12fef 65 case TCP_FIN|TCP_ACK:
nyatla 0:142ee8b12fef 66 case TCP_RST|TCP_ACK:
nyatla 0:142ee8b12fef 67 NyLPC_cIPv4Payload_initTcpTx(i_payload,0x05,((UIP_TCPH_LEN) / 4),0);
nyatla 0:142ee8b12fef 68 NyLPC_cIPv4Payload_setTcpTxHeaderByConnection(i_payload,&(i_inst->uip_connr),i_tcpf);
nyatla 0:142ee8b12fef 69 break;
nyatla 0:142ee8b12fef 70 case TCP_SYN|TCP_ACK:
nyatla 0:142ee8b12fef 71 NyLPC_cIPv4Payload_initTcpTx(i_payload,0x05,((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4),0);
nyatla 0:142ee8b12fef 72 NyLPC_cIPv4Payload_setTcpTxHeaderByConnection(i_payload,&(i_inst->uip_connr),i_tcpf);
nyatla 0:142ee8b12fef 73 //MSSの設定(OPTION領域のアドレス0)
nyatla 0:142ee8b12fef 74 NyLPC_TTcpHeader_setMmsOpt((NyLPC_TUInt8*)(i_payload->payload.tcp+1),i_inst->uip_connr.default_mss);
nyatla 0:142ee8b12fef 75 break;
nyatla 0:142ee8b12fef 76 case TCP_SYN:
nyatla 0:142ee8b12fef 77 NyLPC_cIPv4Payload_initTcpTx(i_payload,0x05,((UIP_TCPH_LEN + TCP_OPT_MSS_LEN) / 4),0);
nyatla 0:142ee8b12fef 78 NyLPC_cIPv4Payload_setTcpTxHeaderByConnection(i_payload,&(i_inst->uip_connr),i_tcpf);
nyatla 0:142ee8b12fef 79 //MSSの設定(OPTION領域のアドレス0)
nyatla 0:142ee8b12fef 80 NyLPC_TTcpHeader_setMmsOpt((NyLPC_TUInt8*)(i_payload->payload.tcp+1),i_inst->uip_connr.default_mss);
nyatla 0:142ee8b12fef 81 break;
nyatla 0:142ee8b12fef 82 default:
nyatla 0:142ee8b12fef 83 NyLPC_Abort();
nyatla 0:142ee8b12fef 84 }
nyatla 0:142ee8b12fef 85 NyLPC_cIPv4Payload_setTcpWnd(i_payload,NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf)));
nyatla 0:142ee8b12fef 86 NyLPC_cIPv4Payload_closeTcpTxPacket(i_payload);
nyatla 0:142ee8b12fef 87 return;
nyatla 0:142ee8b12fef 88 }
nyatla 0:142ee8b12fef 89 /**
nyatla 0:142ee8b12fef 90 * 指定した送信パケットがACK済であるか調べる。
nyatla 0:142ee8b12fef 91 */
nyatla 0:142ee8b12fef 92 static NyLPC_TBool isPacketAcked(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq)
nyatla 0:142ee8b12fef 93 {
nyatla 0:142ee8b12fef 94 int rp;
nyatla 0:142ee8b12fef 95 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 96 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 97 while(rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 98 if(q[rp].ackno==i_sq){
nyatla 0:142ee8b12fef 99 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 100 }
nyatla 0:142ee8b12fef 101 rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 102 }
nyatla 0:142ee8b12fef 103 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 104 }
nyatla 0:142ee8b12fef 105 /**
nyatla 0:142ee8b12fef 106 * 送信キューからi_sq以前に送信したパケットを除外して、残り個数を返却する。
nyatla 0:142ee8b12fef 107 */
nyatla 0:142ee8b12fef 108 static int getNumOfSending(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq)
nyatla 0:142ee8b12fef 109 {
nyatla 0:142ee8b12fef 110 int rp,n;
nyatla 0:142ee8b12fef 111 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 112 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 113 n=0;
nyatla 0:142ee8b12fef 114 while(rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 115 if(q[rp].ackno==i_sq){
nyatla 0:142ee8b12fef 116 return n;
nyatla 0:142ee8b12fef 117 }
nyatla 0:142ee8b12fef 118 n++;
nyatla 0:142ee8b12fef 119 rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 120 }
nyatla 0:142ee8b12fef 121 return n;
nyatla 0:142ee8b12fef 122 }
nyatla 0:142ee8b12fef 123 /**
nyatla 0:142ee8b12fef 124 * この関数は、コネクションをリセットします。
nyatla 0:142ee8b12fef 125 * ロック状態でコールしてください。
nyatla 0:142ee8b12fef 126 * 関数は、現在バッファにある再送信待ちデータを開放します。
nyatla 0:142ee8b12fef 127 */
nyatla 0:142ee8b12fef 128 static void resetTxQWithUnlock(NyLPC_TcTcpSocket_t* i_inst)
nyatla 0:142ee8b12fef 129 {
nyatla 0:142ee8b12fef 130 int i,l;
nyatla 0:142ee8b12fef 131 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 132 void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
nyatla 0:142ee8b12fef 133
nyatla 0:142ee8b12fef 134 l=0;
nyatla 0:142ee8b12fef 135 while(i_inst->txbuf.rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 136 dlist[l]=NyLPC_cIPv4Payload_detachBuf(&(q[i_inst->txbuf.rp].data));
nyatla 0:142ee8b12fef 137 l++;
nyatla 0:142ee8b12fef 138 i_inst->txbuf.rp=(i_inst->txbuf.rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 139 }
nyatla 0:142ee8b12fef 140 i_inst->txbuf.rp=i_inst->txbuf.wp=0;
nyatla 0:142ee8b12fef 141 //ロック解除
nyatla 0:142ee8b12fef 142 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 143 //セーブしたバッファを開放
nyatla 0:142ee8b12fef 144 for(i=0;i<l;i++){
nyatla 0:142ee8b12fef 145 NyLPC_cUipService_releaseTxBuf(dlist[i]);
nyatla 0:142ee8b12fef 146 }
nyatla 0:142ee8b12fef 147 return;
nyatla 0:142ee8b12fef 148 }
nyatla 0:142ee8b12fef 149 /**
nyatla 0:142ee8b12fef 150 * TXバッファの再送パケットのACK番号を更新します。
nyatla 0:142ee8b12fef 151 * ロックして実行してください。
nyatla 0:142ee8b12fef 152 * @param i_ackno
nyatla 0:142ee8b12fef 153 * ネットワークオーダーのACK番号
nyatla 0:142ee8b12fef 154 */
nyatla 0:142ee8b12fef 155 static void updateTxAck(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_ackno)
nyatla 0:142ee8b12fef 156 {
nyatla 0:142ee8b12fef 157 NyLPC_TUInt8 rp;
nyatla 0:142ee8b12fef 158 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 159 NyLPC_ArgAssert(i_inst!=NULL);
nyatla 0:142ee8b12fef 160 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 161 while(rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 162 NyLPC_cIPv4Payload_updateAckNo(&(q[rp].data),i_ackno);
nyatla 0:142ee8b12fef 163 rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 164 }
nyatla 0:142ee8b12fef 165 }
nyatla 0:142ee8b12fef 166
nyatla 0:142ee8b12fef 167 /**
nyatla 0:142ee8b12fef 168 * RTOの予測関数
nyatla 0:142ee8b12fef 169 */
nyatla 0:142ee8b12fef 170 static void estimateRTO(NyLPC_TcTcpSocket_t* i_inst,int s,int n)
nyatla 0:142ee8b12fef 171 {
nyatla 0:142ee8b12fef 172 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 173 NyLPC_TUInt32 cr_rtt_min,cr_rtt_max,sk_rto,new_rto,w;
nyatla 0:142ee8b12fef 174 int i;
nyatla 0:142ee8b12fef 175 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 176 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 177
nyatla 0:142ee8b12fef 178 sk_rto=i_inst->uip_connr.current_rto32;
nyatla 0:142ee8b12fef 179 //ACKされたパケットの個数は?
nyatla 0:142ee8b12fef 180 switch(n){
nyatla 0:142ee8b12fef 181 case 1:
nyatla 0:142ee8b12fef 182 NyLPC_cStopwatch_set(&sw,q[s].tick_of_sent);
nyatla 0:142ee8b12fef 183 cr_rtt_min=NyLPC_cStopwatch_elapseInMsec(&sw);
nyatla 0:142ee8b12fef 184 if(sk_rto<cr_rtt_min){
nyatla 0:142ee8b12fef 185 //現在のRTOよりも大きい→再送があった。(再送の理由が回線遅延によるものかわからないので、基本RTOを25%増やす。)
nyatla 0:142ee8b12fef 186 new_rto=sk_rto*10/8;
nyatla 0:142ee8b12fef 187 }else if(sk_rto/4<cr_rtt_min){
nyatla 0:142ee8b12fef 188 //現在のRTOの1/4< n < 現在のRTO 想定内の変動。1/8
nyatla 0:142ee8b12fef 189 new_rto=(sk_rto+(cr_rtt_min*3*7))/8;
nyatla 0:142ee8b12fef 190 }else{
nyatla 0:142ee8b12fef 191 //現在の1/4以下。RTOを再計算。 RTOが大きすぎるので再計算。(計測値を優先した現在値との平均値)
nyatla 0:142ee8b12fef 192 new_rto=(sk_rto+(cr_rtt_min*3*3))/4;
nyatla 0:142ee8b12fef 193 }
nyatla 0:142ee8b12fef 194 break;
nyatla 0:142ee8b12fef 195 default:
nyatla 0:142ee8b12fef 196 //複数のパケットなら、最大と最小の時刻を得る。
nyatla 0:142ee8b12fef 197 NyLPC_cStopwatch_set(&sw,q[s].tick_of_sent);
nyatla 0:142ee8b12fef 198 cr_rtt_min=cr_rtt_max=NyLPC_cStopwatch_elapseInMsec(&sw);
nyatla 0:142ee8b12fef 199 for(i=1;i<n;i++){
nyatla 0:142ee8b12fef 200 NyLPC_cStopwatch_set(&sw,q[(s+i)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ].tick_of_sent);
nyatla 0:142ee8b12fef 201 w=NyLPC_cStopwatch_elapseInMsec(&sw);
nyatla 0:142ee8b12fef 202 if(cr_rtt_min>w){
nyatla 0:142ee8b12fef 203 cr_rtt_min=w;
nyatla 0:142ee8b12fef 204 }
nyatla 0:142ee8b12fef 205 if(cr_rtt_max<w){
nyatla 0:142ee8b12fef 206 cr_rtt_max=w;
nyatla 0:142ee8b12fef 207 }
nyatla 0:142ee8b12fef 208 }
nyatla 0:142ee8b12fef 209 if(sk_rto<cr_rtt_min && sk_rto<cr_rtt_max){
nyatla 0:142ee8b12fef 210 //最大値,最小値とも現在のRTTより大きい→低速な回線を検出。
nyatla 0:142ee8b12fef 211 new_rto=cr_rtt_max*10/8;//最大経過時間の25%増しの時間を設定。
nyatla 0:142ee8b12fef 212 }else if(sk_rto/4<cr_rtt_min){
nyatla 0:142ee8b12fef 213 //現在のRTOの1/4< n < 現在のRTO 想定範囲内。1/8の加重平均で速度計算。
nyatla 0:142ee8b12fef 214 new_rto=(sk_rto+(cr_rtt_min*3*7))/8;
nyatla 0:142ee8b12fef 215 }else{
nyatla 0:142ee8b12fef 216 //現在の1/4以下。RTOが大きすぎるので再計算。(計測値を優先した加重平均)
nyatla 0:142ee8b12fef 217 new_rto=(sk_rto+(cr_rtt_min*3*3))/4;
nyatla 0:142ee8b12fef 218 }
nyatla 0:142ee8b12fef 219 break;
nyatla 0:142ee8b12fef 220 }
nyatla 0:142ee8b12fef 221 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 222 if(new_rto<UIP_IP_RTO_MINIMUM){
nyatla 0:142ee8b12fef 223 new_rto=UIP_IP_RTO_MINIMUM;
nyatla 0:142ee8b12fef 224 }
nyatla 0:142ee8b12fef 225 i_inst->uip_connr.current_rto32=new_rto;
nyatla 0:142ee8b12fef 226 }
nyatla 0:142ee8b12fef 227
nyatla 0:142ee8b12fef 228 /**
nyatla 0:142ee8b12fef 229 * TXキューから、入力されたシーケンス番号より前のパケットを除外します。
nyatla 0:142ee8b12fef 230 * リングバッファのrp->wp-1までをチェックして、sqに等しいi_sq以前のパケットバッファをo_dlistへ返します。
nyatla 0:142ee8b12fef 231 *
nyatla 0:142ee8b12fef 232 */
nyatla 0:142ee8b12fef 233 static int updateTxQByIndex(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,void* o_dlist[])
nyatla 0:142ee8b12fef 234 {
nyatla 0:142ee8b12fef 235 int rp,n;
nyatla 0:142ee8b12fef 236 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 237 //ロック状態なう
nyatla 0:142ee8b12fef 238 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 239 n=0;
nyatla 0:142ee8b12fef 240 //This is debug
nyatla 0:142ee8b12fef 241 DEBUG_RTO_LOG(i_inst);
nyatla 0:142ee8b12fef 242
nyatla 0:142ee8b12fef 243 while(rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 244 o_dlist[n]=NyLPC_cIPv4Payload_getBuf(&(q[rp].data));
nyatla 0:142ee8b12fef 245 if(q[rp].ackno==i_sq){
nyatla 0:142ee8b12fef 246 //i_inst->txbuf.rp->rpのパケットのRTOからbaseRTOの値を再計算。
nyatla 0:142ee8b12fef 247 estimateRTO(i_inst,i_inst->txbuf.rp,n+1);
nyatla 0:142ee8b12fef 248 i_inst->txbuf.rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 249 return n+1;
nyatla 0:142ee8b12fef 250 }
nyatla 0:142ee8b12fef 251 n++;
nyatla 0:142ee8b12fef 252 rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 253 }
nyatla 0:142ee8b12fef 254 return 0;
nyatla 0:142ee8b12fef 255 }
nyatla 0:142ee8b12fef 256
nyatla 0:142ee8b12fef 257
nyatla 0:142ee8b12fef 258
nyatla 0:142ee8b12fef 259 /**
nyatla 0:142ee8b12fef 260 * 空きキューを1個返します。
nyatla 0:142ee8b12fef 261 * 空きキューの
nyatla 0:142ee8b12fef 262 */
nyatla 0:142ee8b12fef 263 static struct NyLPC_TcTcpSocket_TxQItem* getTxQ(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TcStopwatch_t* i_timer)
nyatla 0:142ee8b12fef 264 {
nyatla 0:142ee8b12fef 265 int i;
nyatla 0:142ee8b12fef 266 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 267 while(!NyLPC_cStopwatch_isExpired(i_timer)){
nyatla 0:142ee8b12fef 268 //クローズドに遷移してしまったら、エラーである。
nyatla 0:142ee8b12fef 269 if(i_inst->tcpstateflags==UIP_CLOSED){
nyatla 0:142ee8b12fef 270 return NULL;
nyatla 0:142ee8b12fef 271 }
nyatla 0:142ee8b12fef 272 //キューの空きをチェック。wp+1==rpなら、キューがいっぱい。rp==wpなら、キューが空。
nyatla 0:142ee8b12fef 273 if(((i_inst->txbuf.wp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ)==i_inst->txbuf.rp){
nyatla 0:142ee8b12fef 274 //一時的なアンロック
nyatla 0:142ee8b12fef 275 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 276 //タスクスイッチ
nyatla 0:142ee8b12fef 277 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 278 //ロック
nyatla 0:142ee8b12fef 279 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 280 continue;
nyatla 0:142ee8b12fef 281 }
nyatla 0:142ee8b12fef 282 i=i_inst->txbuf.wp;
nyatla 0:142ee8b12fef 283 i_inst->txbuf.wp=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
nyatla 0:142ee8b12fef 284 return &(q[i]);
nyatla 0:142ee8b12fef 285 }
nyatla 0:142ee8b12fef 286 //失敗。タイムアウト。
nyatla 0:142ee8b12fef 287 return NULL;
nyatla 0:142ee8b12fef 288 }
nyatla 0:142ee8b12fef 289
nyatla 0:142ee8b12fef 290
nyatla 0:142ee8b12fef 291
nyatla 0:142ee8b12fef 292
nyatla 0:142ee8b12fef 293
nyatla 0:142ee8b12fef 294
nyatla 0:142ee8b12fef 295 /**********************************************************************
nyatla 0:142ee8b12fef 296 * public 関数
nyatla 0:142ee8b12fef 297 **********************************************************************/
nyatla 0:142ee8b12fef 298
nyatla 0:142ee8b12fef 299
nyatla 0:142ee8b12fef 300 NyLPC_TBool NyLPC_cTcpSocket_initialize(NyLPC_TcTcpSocket_t* i_inst,void* i_rbuf,NyLPC_TUInt16 i_rbuf_len)
nyatla 0:142ee8b12fef 301 {
nyatla 0:142ee8b12fef 302 int i;
nyatla 0:142ee8b12fef 303 NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst;
nyatla 0:142ee8b12fef 304 //uipサービスは初期化済であること。
nyatla 0:142ee8b12fef 305 NyLPC_Assert(NyLPC_TcUipService_isInitService());
nyatla 0:142ee8b12fef 306
nyatla 0:142ee8b12fef 307 NyLPC_cFifoBuffer_initialize(&(i_inst->rxbuf),i_rbuf,i_rbuf_len);
nyatla 0:142ee8b12fef 308 NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(i_inst->_smutex)));
nyatla 0:142ee8b12fef 309 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 0:142ee8b12fef 310 i_inst->txbuf.rp=i_inst->txbuf.wp=0;
nyatla 0:142ee8b12fef 311 for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
nyatla 0:142ee8b12fef 312 NyLPC_cIPv4Payload_initialize(&(i_inst->txbuf.txq[i].data));
nyatla 0:142ee8b12fef 313 }
nyatla 0:142ee8b12fef 314 //管理リストへ登録。
nyatla 0:142ee8b12fef 315 return NyLPC_cIPv4_addSocket(&(srv->_tcpv4),i_inst);
nyatla 0:142ee8b12fef 316 }
nyatla 0:142ee8b12fef 317 void NyLPC_cTcpSocket_finalize(NyLPC_TcTcpSocket_t* i_inst,void* i_rbuf,NyLPC_TUInt16 i_rbuf_len)
nyatla 0:142ee8b12fef 318 {
nyatla 0:142ee8b12fef 319 int i;
nyatla 0:142ee8b12fef 320 NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst;
nyatla 0:142ee8b12fef 321 NyLPC_Assert(NyLPC_TcUipService_isInitService());
nyatla 0:142ee8b12fef 322 //uipサービスは初期化済であること。
nyatla 0:142ee8b12fef 323 if(!NyLPC_cIPv4_removeSocket(&(srv->_tcpv4),i_inst)){
nyatla 0:142ee8b12fef 324 //削除失敗、それは死を意味する。
nyatla 0:142ee8b12fef 325 NyLPC_Abort();
nyatla 0:142ee8b12fef 326 }
nyatla 0:142ee8b12fef 327 //開放漏れの保険
nyatla 0:142ee8b12fef 328 if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 329 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 330 resetTxQWithUnlock(i_inst);
nyatla 0:142ee8b12fef 331 }
nyatla 0:142ee8b12fef 332 for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
nyatla 0:142ee8b12fef 333 NyLPC_cIPv4Payload_finalize(&(i_inst->txbuf.txq[i].data));
nyatla 0:142ee8b12fef 334 }
nyatla 0:142ee8b12fef 335 NyLPC_cFifoBuffer_finalize(&(i_inst->rxbuf));
nyatla 0:142ee8b12fef 336 NyLPC_cMutex_finalize(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 337
nyatla 0:142ee8b12fef 338 return;
nyatla 0:142ee8b12fef 339 }
nyatla 0:142ee8b12fef 340
nyatla 0:142ee8b12fef 341 /**
nyatla 0:142ee8b12fef 342 * この関数は、cIPv4Tcpが呼び出すシステムAPIです。
nyatla 0:142ee8b12fef 343 * uipコアタスクが実行します。
nyatla 0:142ee8b12fef 344 * ソケットを、SYNパケットで初期化して、UIP_SYN_RECV状態にします。
nyatla 0:142ee8b12fef 345 * @return
nyatla 0:142ee8b12fef 346 * 遷移に成功すると、TRUEを返します。
nyatla 0:142ee8b12fef 347 */
nyatla 0:142ee8b12fef 348 NyLPC_TBool NyLPC_cTcpSocket_setSynPayload(NyLPC_TcTcpSocket_t* i_inst,const NyLPC_TcIPv4Config_t* i_config,const NyLPC_TcIPv4Payload_t* i_ipp)
nyatla 0:142ee8b12fef 349 {
nyatla 0:142ee8b12fef 350 NyLPC_TUInt16 tmp16;
nyatla 0:142ee8b12fef 351 //ソケットが無効であること。
nyatla 0:142ee8b12fef 352 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 353 if(i_inst->tcpstateflags==UIP_CLOSED)
nyatla 0:142ee8b12fef 354 {
nyatla 0:142ee8b12fef 355 /* Fill in the necessary fields for the new connection. */
nyatla 0:142ee8b12fef 356 i_inst->uip_connr.current_rto32 = UIP_IP_RTOP_INITIAL;
nyatla 0:142ee8b12fef 357 i_inst->uip_connr.lport = i_ipp->payload.tcp->destport;
nyatla 0:142ee8b12fef 358 i_inst->uip_connr.rport = i_ipp->payload.tcp->srcport;
nyatla 0:142ee8b12fef 359 i_inst->uip_connr.ripaddr=i_ipp->header->srcipaddr;
nyatla 0:142ee8b12fef 360 i_inst->uip_connr.snd_nxt32=iss32;
nyatla 0:142ee8b12fef 361 i_inst->uip_connr.lipaddr=&(i_config->ip_addr);
nyatla 0:142ee8b12fef 362 /* rcv_nxt should be the seqno from the incoming packet + 1. */
nyatla 0:142ee8b12fef 363 i_inst->uip_connr.rcv_nxt32= NyLPC_ntohl(i_ipp->payload.tcp->seqno32)+1;
nyatla 0:142ee8b12fef 364 //MSSの設定
nyatla 0:142ee8b12fef 365 i_inst->uip_connr.default_mss=i_inst->uip_connr.peer_mss=i_config->default_mss;
nyatla 0:142ee8b12fef 366 if(NyLPC_TTcpHeader_getTcpMmsOpt(i_ipp->payload.tcp,&tmp16)){
nyatla 0:142ee8b12fef 367 i_inst->uip_connr.peer_mss=tmp16;
nyatla 0:142ee8b12fef 368 }
nyatla 0:142ee8b12fef 369 i_inst->uip_connr.peer_win=0;
nyatla 0:142ee8b12fef 370 NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
nyatla 0:142ee8b12fef 371 //前回のデータが残っていた場合の保険
nyatla 0:142ee8b12fef 372 if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 373 resetTxQWithUnlock(i_inst);
nyatla 0:142ee8b12fef 374 }else{
nyatla 0:142ee8b12fef 375 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 376 }
nyatla 0:142ee8b12fef 377 //ここでステータスがかわる。
nyatla 0:142ee8b12fef 378 i_inst->tcpstateflags = UIP_SYN_RCVD;
nyatla 0:142ee8b12fef 379 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 380 }
nyatla 0:142ee8b12fef 381 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 382 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 383 }
nyatla 0:142ee8b12fef 384 /**
nyatla 0:142ee8b12fef 385 * sq番のTxがキューから消え去るのを待ちます。
nyatla 0:142ee8b12fef 386 * この関数は、アンロック状態でコールしてください。
nyatla 0:142ee8b12fef 387 * <div>
nyatla 0:142ee8b12fef 388 * パケットがキューからなくなる条件は、以下の2つです。
nyatla 0:142ee8b12fef 389 * <ul>
nyatla 0:142ee8b12fef 390 * <li>ACKを受信してパケットキューが更新された。</li>
nyatla 0:142ee8b12fef 391 * <li>RSTを受信して(CLOSEDに遷移して)、キューがクリアされた。</li>
nyatla 0:142ee8b12fef 392 * <li>送信タイムアウトで関数が(CLOSEDに遷移させて)キューをクリアした。</li>
nyatla 0:142ee8b12fef 393 * </ul>
nyatla 0:142ee8b12fef 394 * </div>
nyatla 0:142ee8b12fef 395 * @param i_wait_msec
nyatla 0:142ee8b12fef 396 * @return
nyatla 0:142ee8b12fef 397 * 1番目の条件でパケットが消失したときのみ、TRUEを返します。
nyatla 0:142ee8b12fef 398 * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
nyatla 0:142ee8b12fef 399 */
nyatla 0:142ee8b12fef 400 static NyLPC_TBool waitForTxRemove(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,NyLPC_TcStopwatch_t* i_timer)
nyatla 0:142ee8b12fef 401 {
nyatla 0:142ee8b12fef 402 NyLPC_TUInt8 f;
nyatla 0:142ee8b12fef 403 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 404 while(!NyLPC_cStopwatch_isExpired(i_timer)){
nyatla 0:142ee8b12fef 405 //パケットが送信中か調べる。
nyatla 0:142ee8b12fef 406 if(!isPacketAcked(i_inst,i_sq)){
nyatla 0:142ee8b12fef 407 //まだある場合は、タスクスイッチを繰り返して消失を待つ。
nyatla 0:142ee8b12fef 408 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 409 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 410 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 411 continue;
nyatla 0:142ee8b12fef 412 }
nyatla 0:142ee8b12fef 413 //なくなった場合は、原因を調べる。
nyatla 0:142ee8b12fef 414 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 415 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 416 return (f==UIP_CLOSED)?NyLPC_TBool_FALSE:NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 417 }
nyatla 0:142ee8b12fef 418 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 419 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 420 }
nyatla 0:142ee8b12fef 421
nyatla 0:142ee8b12fef 422
nyatla 0:142ee8b12fef 423
nyatla 0:142ee8b12fef 424
nyatla 0:142ee8b12fef 425 /**
nyatla 0:142ee8b12fef 426 * 再送信処理をセットして、パケットを送信します。
nyatla 0:142ee8b12fef 427 * この関数は「アンロック状態で」実行してください。
nyatla 0:142ee8b12fef 428 * @param i_len
nyatla 0:142ee8b12fef 429 * 送信データサイズを指定します。
nyatla 0:142ee8b12fef 430 * この番号は、シーケンス番号の加算値ではありませんので、注意をしてください。
nyatla 0:142ee8b12fef 431 * @return
nyatla 0:142ee8b12fef 432 * <ul>
nyatla 0:142ee8b12fef 433 * <li>n=-1:送信キューへの投入に失敗した。</li>
nyatla 0:142ee8b12fef 434 * <li>n>=0:nバイトのデータを送信キューへの投入することに成功した。</li>
nyatla 0:142ee8b12fef 435 * </ul>
nyatla 0:142ee8b12fef 436 * 送信キューに失敗する理由は2つあります。1つは、TXバッファがフルでタイムアウト。もうひとつは、非同期なコネクリョンのリセットです。
nyatla 0:142ee8b12fef 437 * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
nyatla 0:142ee8b12fef 438 */
nyatla 0:142ee8b12fef 439 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 440 {
nyatla 0:142ee8b12fef 441 struct NyLPC_TcTcpSocket_TxQItem* txq;
nyatla 0:142ee8b12fef 442 NyLPC_TUInt16 s;
nyatla 0:142ee8b12fef 443 void* buf;
nyatla 0:142ee8b12fef 444 NyLPC_TUInt32 next_ack;
nyatla 0:142ee8b12fef 445
nyatla 0:142ee8b12fef 446
nyatla 0:142ee8b12fef 447 //送信バッファを取得
nyatla 0:142ee8b12fef 448 buf=NyLPC_cUipService_allocTxBuf(i_len+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
nyatla 0:142ee8b12fef 449 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 450 //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
nyatla 0:142ee8b12fef 451 if(i_len>0){
nyatla 0:142ee8b12fef 452 while(i_inst->uip_connr.peer_win==0){
nyatla 0:142ee8b12fef 453 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 454 //時間切れならエラー。
nyatla 0:142ee8b12fef 455 if(NyLPC_cStopwatch_isExpired(i_timer)){
nyatla 0:142ee8b12fef 456 return -1;
nyatla 0:142ee8b12fef 457 }
nyatla 0:142ee8b12fef 458 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 459 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 460 }
nyatla 0:142ee8b12fef 461 }
nyatla 0:142ee8b12fef 462 //送信キューの取得
nyatla 0:142ee8b12fef 463 txq=getTxQ(i_inst,i_timer);
nyatla 0:142ee8b12fef 464 //送信キューが取れなかった。
nyatla 0:142ee8b12fef 465 if(txq==NULL){
nyatla 0:142ee8b12fef 466 //シーケンス番号をロールバックできないので、エラーとする。
nyatla 0:142ee8b12fef 467 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 468 NyLPC_cUipService_releaseTxBuf(buf);
nyatla 0:142ee8b12fef 469 return -1;
nyatla 0:142ee8b12fef 470 }
nyatla 0:142ee8b12fef 471 //IPv4ペイロードの書き込み
nyatla 0:142ee8b12fef 472 NyLPC_cIPv4Payload_setTxBuf(&(txq->data),buf);
nyatla 0:142ee8b12fef 473
nyatla 0:142ee8b12fef 474 //送信バッファを基準とした送信サイズを計算
nyatla 0:142ee8b12fef 475 s-=SIZE_OF_IPv4_TCPIP_HEADER;
nyatla 0:142ee8b12fef 476 //送信サイズよりMMSが小さければ、送信サイズを修正
nyatla 0:142ee8b12fef 477 if(i_inst->uip_connr.peer_mss<s){
nyatla 0:142ee8b12fef 478 s=i_inst->uip_connr.peer_mss;
nyatla 0:142ee8b12fef 479 }
nyatla 0:142ee8b12fef 480 //送信サイズよりpeerのウインドウサイズが小さければ修正
nyatla 0:142ee8b12fef 481 if(i_inst->uip_connr.peer_win<s){
nyatla 0:142ee8b12fef 482 s=i_inst->uip_connr.peer_win;
nyatla 0:142ee8b12fef 483 }
nyatla 0:142ee8b12fef 484 //送信サイズより、データサイズが小さければ、送信サイズを修正
nyatla 0:142ee8b12fef 485 if(i_len<s){
nyatla 0:142ee8b12fef 486 s=i_len;
nyatla 0:142ee8b12fef 487 }
nyatla 0:142ee8b12fef 488 //ACK番号の計算
nyatla 0:142ee8b12fef 489 next_ack=i_inst->uip_connr.snd_nxt32+s+((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00?1:0);
nyatla 0:142ee8b12fef 490 txq->rto32=i_inst->uip_connr.current_rto32;
nyatla 0:142ee8b12fef 491 txq->tick_of_sent=NyLPC_cStopwatch_now();
nyatla 0:142ee8b12fef 492
nyatla 0:142ee8b12fef 493 //パケットの書き込み
nyatla 0:142ee8b12fef 494 setPacket(i_inst,&(txq->data),i_tcpf,i_buf,s);
nyatla 0:142ee8b12fef 495 //シーケンス番号の更新
nyatla 0:142ee8b12fef 496 i_inst->uip_connr.snd_nxt32=next_ack;
nyatla 0:142ee8b12fef 497 //Peerのウインドウサイズを更新
nyatla 0:142ee8b12fef 498 i_inst->uip_connr.peer_win-=s;
nyatla 0:142ee8b12fef 499 //ACK番号の返却
nyatla 0:142ee8b12fef 500 *o_ack=txq->ackno=NyLPC_HTONL(next_ack);
nyatla 0:142ee8b12fef 501 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 502 NyLPC_cUipService_sendIPv4Tx(buf);
nyatla 0:142ee8b12fef 503 return s;
nyatla 0:142ee8b12fef 504 }
nyatla 0:142ee8b12fef 505 /**
nyatla 0:142ee8b12fef 506 * RSTを1フレームだけ送信します。
nyatla 0:142ee8b12fef 507 * この関数は、クローズドステータスのソケットにしてからコールします。
nyatla 0:142ee8b12fef 508 * この関数は、アンロック状態でコールしてね。
nyatla 0:142ee8b12fef 509 */
nyatla 0:142ee8b12fef 510 static void sendRst(NyLPC_TcTcpSocket_t* i_inst)
nyatla 0:142ee8b12fef 511 {
nyatla 0:142ee8b12fef 512 NyLPC_TcIPv4Payload_t ipv4;
nyatla 0:142ee8b12fef 513 NyLPC_TUInt16 s;
nyatla 0:142ee8b12fef 514 void* buf;
nyatla 0:142ee8b12fef 515
nyatla 0:142ee8b12fef 516 NyLPC_Assert(i_inst->tcpstateflags==UIP_CLOSED);
nyatla 0:142ee8b12fef 517 //ペイロードライタの初期化
nyatla 0:142ee8b12fef 518 NyLPC_cIPv4Payload_initialize(&ipv4);
nyatla 0:142ee8b12fef 519
nyatla 0:142ee8b12fef 520 //IPヘッダ+10バイトくらい。
nyatla 0:142ee8b12fef 521 buf=NyLPC_cUipService_allocTxBuf((SIZE_OF_IPv4_TCPIP_HEADER)+5,&s);
nyatla 0:142ee8b12fef 522
nyatla 0:142ee8b12fef 523 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 524 NyLPC_cIPv4Payload_setTxBuf(&ipv4,buf);
nyatla 0:142ee8b12fef 525 i_inst->uip_connr.snd_nxt32++;
nyatla 0:142ee8b12fef 526 setPacket(i_inst,&ipv4,TCP_RST|TCP_ACK,buf,0);
nyatla 0:142ee8b12fef 527 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 528
nyatla 0:142ee8b12fef 529 NyLPC_cUipService_sendIPv4Tx(buf);
nyatla 0:142ee8b12fef 530 NyLPC_cUipService_releaseTxBuf(buf);
nyatla 0:142ee8b12fef 531 NyLPC_cIPv4Payload_finalize(&ipv4);
nyatla 0:142ee8b12fef 532 return;
nyatla 0:142ee8b12fef 533 }
nyatla 0:142ee8b12fef 534
nyatla 0:142ee8b12fef 535
nyatla 0:142ee8b12fef 536
nyatla 0:142ee8b12fef 537 /**
nyatla 0:142ee8b12fef 538 * 受信データを排他処理してバッファに書き込む。
nyatla 0:142ee8b12fef 539 * 十分な空き領域がない場合、失敗する。
nyatla 0:142ee8b12fef 540 * この関数は、ロックして実行してください。
nyatla 0:142ee8b12fef 541 */
nyatla 0:142ee8b12fef 542 static NyLPC_TBool addRecvData(NyLPC_TcTcpSocket_t* i_inst,void* i_data,NyLPC_TUInt16 i_data_size)
nyatla 0:142ee8b12fef 543 {
nyatla 0:142ee8b12fef 544 //受信データサイズを確認
nyatla 0:142ee8b12fef 545 if(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf))>=i_data_size){
nyatla 0:142ee8b12fef 546 //バッファに格納可能なら、格納。
nyatla 0:142ee8b12fef 547 NyLPC_cFifoBuffer_push(&(i_inst->rxbuf),i_data,i_data_size);
nyatla 0:142ee8b12fef 548 }else{
nyatla 0:142ee8b12fef 549 //エラー:ドロップする。
nyatla 0:142ee8b12fef 550 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 551 }
nyatla 0:142ee8b12fef 552 return NyLPC_TBool_TRUE;
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 * Public function
nyatla 0:142ee8b12fef 560 */
nyatla 0:142ee8b12fef 561
nyatla 0:142ee8b12fef 562 /**
nyatla 0:142ee8b12fef 563 * この関数は、UIP_SYN_RCVDステータスのソケットを、ESTABLISHEDへ遷移させます。
nyatla 0:142ee8b12fef 564 * cTcpListener_listen関数を通過したインスタンスに実行してください。
nyatla 0:142ee8b12fef 565 * この関数は、アプリケーションが呼び出します。
nyatla 0:142ee8b12fef 566 * @return
nyatla 0:142ee8b12fef 567 *
nyatla 0:142ee8b12fef 568 */
nyatla 0:142ee8b12fef 569 NyLPC_TBool NyLPC_cTcpSocket_accept(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
nyatla 0:142ee8b12fef 570 {
nyatla 0:142ee8b12fef 571 volatile NyLPC_TUInt8 f;
nyatla 0:142ee8b12fef 572 NyLPC_TUInt32 sq;
nyatla 0:142ee8b12fef 573 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 574
nyatla 0:142ee8b12fef 575 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 576 //ステータスチェック
nyatla 0:142ee8b12fef 577 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 578 switch(f)
nyatla 0:142ee8b12fef 579 {
nyatla 0:142ee8b12fef 580 case UIP_ESTABLISHED:
nyatla 0:142ee8b12fef 581 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 582 case UIP_SYN_RCVD:
nyatla 0:142ee8b12fef 583 //処理対象
nyatla 0:142ee8b12fef 584 break;
nyatla 0:142ee8b12fef 585 default:
nyatla 0:142ee8b12fef 586 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 587 }
nyatla 0:142ee8b12fef 588 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 0:142ee8b12fef 589 if(sendWithRetransmit(i_inst,TCP_SYN|TCP_ACK,NULL,0,&sw,&sq)==0){
nyatla 0:142ee8b12fef 590 //ちょっと待つ。
nyatla 0:142ee8b12fef 591 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 592 //キューにあるTXが消えるのを待つ。
nyatla 0:142ee8b12fef 593 if(waitForTxRemove(i_inst,sq,&sw)){
nyatla 0:142ee8b12fef 594 //ACK受信に成功して、TXが消失
nyatla 0:142ee8b12fef 595 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 596 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 597 }
nyatla 0:142ee8b12fef 598 }
nyatla 0:142ee8b12fef 599 //ロックして、強制的なステータス遷移
nyatla 0:142ee8b12fef 600 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 601 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 602 if(f!=UIP_CLOSED){
nyatla 0:142ee8b12fef 603 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 0:142ee8b12fef 604 }
nyatla 0:142ee8b12fef 605 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 606 //もし、強制CLOSE遷移であれば、RSTも送信。
nyatla 0:142ee8b12fef 607 if(f!=UIP_CLOSED){
nyatla 0:142ee8b12fef 608 sendRst(i_inst);
nyatla 0:142ee8b12fef 609 }
nyatla 0:142ee8b12fef 610 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 611 }
nyatla 0:142ee8b12fef 612
nyatla 0:142ee8b12fef 613
nyatla 0:142ee8b12fef 614 /**
nyatla 0:142ee8b12fef 615 * この関数は、ソケットの受信バッファの読み取り位置と、読み出せるデータサイズを返却します。
nyatla 0:142ee8b12fef 616 * 関数はポインターを返却するだけで、バッファの読み取り位置をシークしません。
nyatla 0:142ee8b12fef 617 * シークするにはNyLPC_cTcpSocket_pseekを使います。
nyatla 0:142ee8b12fef 618 */
nyatla 0:142ee8b12fef 619 NyLPC_TInt32 NyLPC_cTcpSocket_precv(NyLPC_TcTcpSocket_t* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec)
nyatla 0:142ee8b12fef 620 {
nyatla 0:142ee8b12fef 621 volatile NyLPC_TUInt8 st;
nyatla 0:142ee8b12fef 622 NyLPC_TUInt16 rlen;
nyatla 0:142ee8b12fef 623 //タイマを生成
nyatla 0:142ee8b12fef 624 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 625 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 626
nyatla 0:142ee8b12fef 627 //ESTABLISHED以外の場合は、エラー。
nyatla 0:142ee8b12fef 628 NyLPC_cStopwatch_setNow(&sw);
nyatla 0:142ee8b12fef 629 while(NyLPC_cStopwatch_elapseInMsec(&sw)<i_wait_msec)
nyatla 0:142ee8b12fef 630 {
nyatla 0:142ee8b12fef 631 //読み出しバッファ情報のコピー
nyatla 0:142ee8b12fef 632
nyatla 0:142ee8b12fef 633 //MUTEX LOCK
nyatla 0:142ee8b12fef 634 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 635 st=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 636 rlen=NyLPC_cFifoBuffer_getLength(&(i_inst->rxbuf));
nyatla 0:142ee8b12fef 637 *o_buf_ptr=NyLPC_cFifoBuffer_getPtr(&(i_inst->rxbuf));
nyatla 0:142ee8b12fef 638 //MUTEX UNLOCK
nyatla 0:142ee8b12fef 639 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 640
nyatla 0:142ee8b12fef 641 //バッファが空の場合は、ステータスチェック。ESTABLISHEDでなければ、エラー(PASVCLOSE等の場合)
nyatla 0:142ee8b12fef 642 switch(st){
nyatla 0:142ee8b12fef 643 case UIP_ESTABLISHED:
nyatla 0:142ee8b12fef 644 if(rlen>0){
nyatla 0:142ee8b12fef 645 //バッファにパケットがあれば返却
nyatla 0:142ee8b12fef 646 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 647 return rlen;
nyatla 0:142ee8b12fef 648 }
nyatla 0:142ee8b12fef 649 break;
nyatla 0:142ee8b12fef 650 case UIP_CLOSE_WAIT:
nyatla 0:142ee8b12fef 651 if(rlen>0){
nyatla 0:142ee8b12fef 652 //バッファにパケットがあれば返却
nyatla 0:142ee8b12fef 653 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 654 return rlen;
nyatla 0:142ee8b12fef 655 }
nyatla 0:142ee8b12fef 656 //引き続きエラー処理
nyatla 0:142ee8b12fef 657 default:
nyatla 0:142ee8b12fef 658 //他の場合はエラー
nyatla 0:142ee8b12fef 659 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 660 return -1;
nyatla 0:142ee8b12fef 661 }
nyatla 0:142ee8b12fef 662 //タスクスイッチ
nyatla 0:142ee8b12fef 663 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 664 };
nyatla 0:142ee8b12fef 665 //規定時間内に受信が成功しなかった。
nyatla 0:142ee8b12fef 666 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 667 return 0;
nyatla 0:142ee8b12fef 668 }
nyatla 0:142ee8b12fef 669 /**
nyatla 0:142ee8b12fef 670 * 受信バッファをシークします。
nyatla 0:142ee8b12fef 671 * シーク後に、遅延ACKを送出します。
nyatla 0:142ee8b12fef 672 */
nyatla 0:142ee8b12fef 673 void NyLPC_cTcpSocket_pseek(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt16 i_seek)
nyatla 0:142ee8b12fef 674 {
nyatla 0:142ee8b12fef 675 NyLPC_TcIPv4Payload_t ipv4payload;
nyatla 0:142ee8b12fef 676 void* buf;
nyatla 0:142ee8b12fef 677 NyLPC_TUInt16 s;
nyatla 0:142ee8b12fef 678 NyLPC_ArgAssert(i_seek<=NyLPC_cFifoBuffer_getLength(&(i_inst->rxbuf)));
nyatla 0:142ee8b12fef 679 if(i_seek==0){
nyatla 0:142ee8b12fef 680 return;
nyatla 0:142ee8b12fef 681 }
nyatla 0:142ee8b12fef 682 //ペイロードライタの初期化
nyatla 0:142ee8b12fef 683 NyLPC_cIPv4Payload_initialize(&ipv4payload);
nyatla 0:142ee8b12fef 684
nyatla 0:142ee8b12fef 685 //ACK送信バッファの取得
nyatla 0:142ee8b12fef 686 buf=NyLPC_cUipService_allocTxBuf((SIZE_OF_IPv4_TCPIP_HEADER)+5,&s);
nyatla 0:142ee8b12fef 687
nyatla 0:142ee8b12fef 688 //MUTEX LOCK
nyatla 0:142ee8b12fef 689 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 690
nyatla 0:142ee8b12fef 691 //受信バッファを読み出しシーク
nyatla 0:142ee8b12fef 692 NyLPC_cFifoBuffer_pop(&(i_inst->rxbuf),i_seek);
nyatla 0:142ee8b12fef 693 //ACKパケットの生成
nyatla 0:142ee8b12fef 694 NyLPC_cIPv4Payload_setTxBuf(&ipv4payload,buf);
nyatla 0:142ee8b12fef 695 setPacket(i_inst,&ipv4payload,TCP_ACK,buf,0);
nyatla 0:142ee8b12fef 696 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 697 //ACK送信
nyatla 0:142ee8b12fef 698 NyLPC_cUipService_sendIPv4Tx(buf);
nyatla 0:142ee8b12fef 699 NyLPC_cUipService_releaseTxBuf(buf);
nyatla 0:142ee8b12fef 700 //ペイロードライタの破棄
nyatla 0:142ee8b12fef 701 NyLPC_cIPv4Payload_finalize(&ipv4payload);
nyatla 0:142ee8b12fef 702 }
nyatla 0:142ee8b12fef 703
nyatla 0:142ee8b12fef 704 /**
nyatla 0:142ee8b12fef 705 * See header file.
nyatla 0:142ee8b12fef 706 */
nyatla 0:142ee8b12fef 707 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 708 {
nyatla 0:142ee8b12fef 709 NyLPC_TUInt16 s;
nyatla 0:142ee8b12fef 710 void* buf;
nyatla 0:142ee8b12fef 711 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 712
nyatla 0:142ee8b12fef 713 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 714 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 0:142ee8b12fef 715
nyatla 0:142ee8b12fef 716 //送信バッファを取得
nyatla 0:142ee8b12fef 717 buf=NyLPC_cUipService_allocTxBuf(i_hint+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
nyatla 0:142ee8b12fef 718 //ここ、要求サイズとpeerのwinのうち、小さいほうを割り当てたほうが良くない?
nyatla 0:142ee8b12fef 719 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 720 //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
nyatla 0:142ee8b12fef 721 while(i_inst->uip_connr.peer_win==0){
nyatla 0:142ee8b12fef 722 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 723 //時間切れならエラー。
nyatla 0:142ee8b12fef 724 if(NyLPC_cStopwatch_isExpired(&sw)){
nyatla 0:142ee8b12fef 725 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 726 return NULL;
nyatla 0:142ee8b12fef 727 }
nyatla 0:142ee8b12fef 728 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 729 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 730 }
nyatla 0:142ee8b12fef 731 //送信バッファを基準とした送信サイズを計算
nyatla 0:142ee8b12fef 732 s-=SIZE_OF_IPv4_TCPIP_HEADER;
nyatla 0:142ee8b12fef 733 //送信サイズよりMMSが小さければ、送信サイズを修正
nyatla 0:142ee8b12fef 734 if(i_inst->uip_connr.peer_mss<s){
nyatla 0:142ee8b12fef 735 s=i_inst->uip_connr.peer_mss;
nyatla 0:142ee8b12fef 736 }
nyatla 0:142ee8b12fef 737 //送信サイズよりpeerのウインドウサイズが小さければ修正
nyatla 0:142ee8b12fef 738 if(i_inst->uip_connr.peer_win<s){
nyatla 0:142ee8b12fef 739 s=i_inst->uip_connr.peer_win;
nyatla 0:142ee8b12fef 740 }
nyatla 0:142ee8b12fef 741 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 742 //バッファサイズ確定。
nyatla 0:142ee8b12fef 743 *o_buf_size=s;
nyatla 0:142ee8b12fef 744 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 745 return (NyLPC_TUInt8*)buf+SIZE_OF_IPv4_TCPIP_HEADER;
nyatla 0:142ee8b12fef 746 }
nyatla 0:142ee8b12fef 747 /**
nyatla 0:142ee8b12fef 748 * See Header file.
nyatla 0:142ee8b12fef 749 */
nyatla 0:142ee8b12fef 750 void NyLPC_cTcpSocket_releaseSendBuf(NyLPC_TcTcpSocket_t* i_inst,void* i_buf_ptr)
nyatla 0:142ee8b12fef 751 {
nyatla 0:142ee8b12fef 752 NyLPC_cUipService_releaseTxBuf((NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER);
nyatla 0:142ee8b12fef 753 }
nyatla 0:142ee8b12fef 754
nyatla 0:142ee8b12fef 755
nyatla 0:142ee8b12fef 756 /**
nyatla 0:142ee8b12fef 757 * 事前にAllocしたTxパケットを送信します。
nyatla 0:142ee8b12fef 758 * このAPIはゼロコピー送信をサポートするためのものです。
nyatla 0:142ee8b12fef 759 * @param i_buf_ptr
nyatla 0:142ee8b12fef 760 * allocSendBufで取得したメモリを指定します。
nyatla 0:142ee8b12fef 761 * @return
nyatla 0:142ee8b12fef 762 * 関数が失敗した場合、i_buf_ptrは「開放されません。」
nyatla 0:142ee8b12fef 763 */
nyatla 0:142ee8b12fef 764 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 765 {
nyatla 0:142ee8b12fef 766 struct NyLPC_TcTcpSocket_TxQItem* txq;
nyatla 0:142ee8b12fef 767 void* buf;
nyatla 0:142ee8b12fef 768 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 769
nyatla 0:142ee8b12fef 770 //ESTABLISHEDでなければエラー
nyatla 0:142ee8b12fef 771 if(i_inst->tcpstateflags!=UIP_ESTABLISHED){
nyatla 0:142ee8b12fef 772 //ESTABLISHEDでなければエラー
nyatla 0:142ee8b12fef 773 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 774 }
nyatla 0:142ee8b12fef 775 //送信データ0ならエラー
nyatla 0:142ee8b12fef 776 if(i_len<1){
nyatla 0:142ee8b12fef 777 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 778 }
nyatla 0:142ee8b12fef 779 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 780 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 0:142ee8b12fef 781
nyatla 0:142ee8b12fef 782 //先頭ポインタは、i_buf-sizeof(SIZE_OF_IPv4_TCPIP_HEADER)固定
nyatla 0:142ee8b12fef 783 buf=(NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER;
nyatla 0:142ee8b12fef 784 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 785 //送信キューの取得
nyatla 0:142ee8b12fef 786 txq=getTxQ(i_inst,&sw);
nyatla 0:142ee8b12fef 787 //送信キューが取れなかった。
nyatla 0:142ee8b12fef 788 if(txq==NULL){
nyatla 0:142ee8b12fef 789 //シーケンス番号をロールバックできないので、エラーとする。
nyatla 0:142ee8b12fef 790 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 791 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 792 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 793 }
nyatla 0:142ee8b12fef 794 //ここから先はi_bufの所有権はインスタンスになってる。
nyatla 0:142ee8b12fef 795
nyatla 0:142ee8b12fef 796 //IPv4ペイロードの書き込み
nyatla 0:142ee8b12fef 797 NyLPC_cIPv4Payload_setTxBuf(&(txq->data),buf);
nyatla 0:142ee8b12fef 798 //allocをした時点でwin,mssは考慮されているので、そのままそうしんしる。
nyatla 0:142ee8b12fef 799 //ACK番号の計算
nyatla 0:142ee8b12fef 800 txq->rto32=i_inst->uip_connr.current_rto32;
nyatla 0:142ee8b12fef 801 txq->tick_of_sent=NyLPC_cStopwatch_now();
nyatla 0:142ee8b12fef 802 //パケットヘッダの生成
nyatla 0:142ee8b12fef 803 NyLPC_cIPv4Payload_initTcpTx(&(txq->data),0x05,((UIP_TCPH_LEN) / 4),i_len);
nyatla 0:142ee8b12fef 804 NyLPC_cIPv4Payload_setTcpTxHeaderByConnection(&(txq->data),&(i_inst->uip_connr),TCP_ACK|TCP_PSH);
nyatla 0:142ee8b12fef 805 NyLPC_cIPv4Payload_setTcpWnd(&(txq->data),NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf)));
nyatla 0:142ee8b12fef 806 NyLPC_cIPv4Payload_closeTcpTxPacket(&(txq->data));
nyatla 0:142ee8b12fef 807 //シーケンス番号の更新
nyatla 0:142ee8b12fef 808 i_inst->uip_connr.snd_nxt32=i_inst->uip_connr.snd_nxt32+i_len;
nyatla 0:142ee8b12fef 809 //Peerのウインドウサイズを更新
nyatla 0:142ee8b12fef 810 i_inst->uip_connr.peer_win-=i_len;
nyatla 0:142ee8b12fef 811 //ACK番号の返却
nyatla 0:142ee8b12fef 812 txq->ackno=NyLPC_HTONL(i_inst->uip_connr.snd_nxt32);
nyatla 0:142ee8b12fef 813 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 814 NyLPC_cUipService_sendIPv4Tx(buf);
nyatla 0:142ee8b12fef 815 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 816 return NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 817 }
nyatla 0:142ee8b12fef 818
nyatla 0:142ee8b12fef 819 /**
nyatla 0:142ee8b12fef 820 * See header file.
nyatla 0:142ee8b12fef 821 */
nyatla 0:142ee8b12fef 822 NyLPC_TInt16 NyLPC_cTcpSocket_send(NyLPC_TcTcpSocket_t* i_inst,const void* i_buf_ptr,int i_len,NyLPC_TUInt32 i_wait_in_msec)
nyatla 0:142ee8b12fef 823 {
nyatla 0:142ee8b12fef 824 NyLPC_TUInt32 sq;
nyatla 0:142ee8b12fef 825 NyLPC_TInt32 r;
nyatla 0:142ee8b12fef 826 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 827 //ESTABLISHEDでなければエラー
nyatla 0:142ee8b12fef 828 if(i_inst->tcpstateflags!=UIP_ESTABLISHED){
nyatla 0:142ee8b12fef 829 //ESTABLISHEDでなければエラー
nyatla 0:142ee8b12fef 830 return -1;
nyatla 0:142ee8b12fef 831 }
nyatla 0:142ee8b12fef 832 if(i_len<1){
nyatla 0:142ee8b12fef 833 return 0;
nyatla 0:142ee8b12fef 834 }
nyatla 0:142ee8b12fef 835 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 836 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 0:142ee8b12fef 837 //PSHACKを送信する。
nyatla 0:142ee8b12fef 838 r=sendWithRetransmit(i_inst,TCP_PSH|TCP_ACK,i_buf_ptr,i_len,&sw,&sq);
nyatla 0:142ee8b12fef 839 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 840 //失敗時も何もしない?強制CLOSEしなくて平気?
nyatla 0:142ee8b12fef 841 return r;
nyatla 0:142ee8b12fef 842 }
nyatla 0:142ee8b12fef 843
nyatla 0:142ee8b12fef 844
nyatla 0:142ee8b12fef 845 void NyLPC_cTcpSocket_close(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
nyatla 0:142ee8b12fef 846 {
nyatla 0:142ee8b12fef 847 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 848 volatile NyLPC_TUInt8 f;
nyatla 0:142ee8b12fef 849 NyLPC_TUInt32 sq;
nyatla 0:142ee8b12fef 850 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 851 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
nyatla 0:142ee8b12fef 852 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 853
nyatla 0:142ee8b12fef 854 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 855 //ステータスチェック
nyatla 0:142ee8b12fef 856 switch(f)
nyatla 0:142ee8b12fef 857 {
nyatla 0:142ee8b12fef 858 case UIP_CLOSED:
nyatla 0:142ee8b12fef 859 //閉じている。
nyatla 0:142ee8b12fef 860 goto ReturnWithUnlock;
nyatla 0:142ee8b12fef 861 case UIP_ESTABLISHED:
nyatla 0:142ee8b12fef 862 //アクティブクローズ。
nyatla 0:142ee8b12fef 863 i_inst->tcpstateflags=UIP_FIN_WAIT_1;
nyatla 0:142ee8b12fef 864 //送信のために一旦解除
nyatla 0:142ee8b12fef 865 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 866 //FINの送信
nyatla 0:142ee8b12fef 867 if(sendWithRetransmit(i_inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
nyatla 0:142ee8b12fef 868 //ちょっと待つ。
nyatla 0:142ee8b12fef 869 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 870 //TXの消去待ち
nyatla 0:142ee8b12fef 871 if(waitForTxRemove(i_inst,sq,&sw)){
nyatla 0:142ee8b12fef 872 //再ロック
nyatla 0:142ee8b12fef 873 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 874 //タイムアウトするか、UIP_CLOSED、もしくはTIME_WAITに遷移するのを待つ。(遷移はRxprocで自動的に実行。)
nyatla 0:142ee8b12fef 875 while(!NyLPC_cStopwatch_isExpired(&sw)){
nyatla 0:142ee8b12fef 876 switch(i_inst->tcpstateflags)
nyatla 0:142ee8b12fef 877 {
nyatla 0:142ee8b12fef 878 case UIP_TIME_WAIT:
nyatla 0:142ee8b12fef 879 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 0:142ee8b12fef 880 case UIP_CLOSED:
nyatla 0:142ee8b12fef 881 NyLPC_Assert(i_inst->txbuf.rp==i_inst->txbuf.wp);
nyatla 0:142ee8b12fef 882 //成功。
nyatla 0:142ee8b12fef 883 goto ReturnWithUnlock;
nyatla 0:142ee8b12fef 884 case UIP_FIN_WAIT_1:
nyatla 0:142ee8b12fef 885 case UIP_FIN_WAIT_2:
nyatla 0:142ee8b12fef 886 case UIP_CLOSING:
nyatla 0:142ee8b12fef 887 //一時的なアンロック
nyatla 0:142ee8b12fef 888 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 889 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 890 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 891 default:
nyatla 0:142ee8b12fef 892 break;
nyatla 0:142ee8b12fef 893 }
nyatla 0:142ee8b12fef 894 }
nyatla 0:142ee8b12fef 895 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 896 }
nyatla 0:142ee8b12fef 897 }
nyatla 0:142ee8b12fef 898 break;
nyatla 0:142ee8b12fef 899 case UIP_CLOSE_WAIT:
nyatla 0:142ee8b12fef 900 //LAST_ACKへ遷移
nyatla 0:142ee8b12fef 901 i_inst->tcpstateflags=UIP_LAST_ACK;
nyatla 0:142ee8b12fef 902 //送信のために一旦解除
nyatla 0:142ee8b12fef 903 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 904 if(sendWithRetransmit(i_inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
nyatla 0:142ee8b12fef 905 //ちょっと待つ。
nyatla 0:142ee8b12fef 906 NyLPC_cThread_yield();
nyatla 0:142ee8b12fef 907 //TXの消去待ち
nyatla 0:142ee8b12fef 908 if(waitForTxRemove(i_inst,sq,&sw)){
nyatla 0:142ee8b12fef 909 //再ロック
nyatla 0:142ee8b12fef 910 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 911 //TX消去後にCLOSEDに遷移していればOK
nyatla 0:142ee8b12fef 912 if(i_inst->tcpstateflags==UIP_CLOSED)
nyatla 0:142ee8b12fef 913 {
nyatla 0:142ee8b12fef 914 NyLPC_Assert(i_inst->txbuf.rp==i_inst->txbuf.wp);
nyatla 0:142ee8b12fef 915 goto ReturnWithUnlock;
nyatla 0:142ee8b12fef 916 }
nyatla 0:142ee8b12fef 917 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 918 }
nyatla 0:142ee8b12fef 919 }
nyatla 0:142ee8b12fef 920 //エラー。RSTで切断。
nyatla 0:142ee8b12fef 921 break;
nyatla 0:142ee8b12fef 922 default:
nyatla 0:142ee8b12fef 923 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 924 NyLPC_Warning();
nyatla 0:142ee8b12fef 925 break;
nyatla 0:142ee8b12fef 926 }
nyatla 0:142ee8b12fef 927 if(i_inst->_smutex._lock_count>0){
nyatla 0:142ee8b12fef 928 NyLPC_Warning();
nyatla 0:142ee8b12fef 929 }
nyatla 0:142ee8b12fef 930 //このパスに到達するのは、FIN送信/ACKに成功したにも拘らず、規定時間内にCLOSEDに遷移しなかった場合。
nyatla 0:142ee8b12fef 931 //コネクションを強制遷移して、RST
nyatla 0:142ee8b12fef 932 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 933 f=i_inst->tcpstateflags;
nyatla 0:142ee8b12fef 934 if(f!=UIP_CLOSED){
nyatla 0:142ee8b12fef 935 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 0:142ee8b12fef 936 }
nyatla 0:142ee8b12fef 937 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 938 //もし、強制CLOSE遷移であれば、RSTも送信。
nyatla 0:142ee8b12fef 939 if(f!=UIP_CLOSED){
nyatla 0:142ee8b12fef 940 sendRst(i_inst);
nyatla 0:142ee8b12fef 941 }
nyatla 0:142ee8b12fef 942 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 943 return;
nyatla 0:142ee8b12fef 944 ReturnWithUnlock:
nyatla 0:142ee8b12fef 945 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 946 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 947 return;
nyatla 0:142ee8b12fef 948 }
nyatla 0:142ee8b12fef 949
nyatla 0:142ee8b12fef 950 /**
nyatla 0:142ee8b12fef 951 * 定期的に実行する関数。最低でも1s単位で実行してください。
nyatla 0:142ee8b12fef 952 * 動作
nyatla 0:142ee8b12fef 953 */
nyatla 0:142ee8b12fef 954 void NyLPC_cTcpSocket_periodic(
nyatla 0:142ee8b12fef 955 NyLPC_TcTcpSocket_t* i_inst)
nyatla 0:142ee8b12fef 956 {
nyatla 0:142ee8b12fef 957 int i;
nyatla 0:142ee8b12fef 958 struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
nyatla 0:142ee8b12fef 959 NyLPC_TcStopwatch_t sw;
nyatla 0:142ee8b12fef 960 NyLPC_TUInt32 now;
nyatla 0:142ee8b12fef 961 int rp;
nyatla 0:142ee8b12fef 962 NyLPC_cStopwatch_initialize(&sw);
nyatla 0:142ee8b12fef 963 now=NyLPC_cStopwatch_now();
nyatla 0:142ee8b12fef 964 //MUTEX LOCK
nyatla 0:142ee8b12fef 965 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 966 if(i_inst->tcpstateflags==UIP_CLOSED)
nyatla 0:142ee8b12fef 967 {
nyatla 0:142ee8b12fef 968 //CLOSEDなら、バッファ開放。
nyatla 0:142ee8b12fef 969 resetTxQWithUnlock(i_inst);
nyatla 0:142ee8b12fef 970 }else if(i_inst->txbuf.rp==i_inst->txbuf.wp){
nyatla 0:142ee8b12fef 971 //再送信パケットがなければ何もしないよ。
nyatla 0:142ee8b12fef 972 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 973 }else if(i_inst->uip_connr.peer_win==0){
nyatla 0:142ee8b12fef 974 //peer_winが0の場合は何もしない。
nyatla 0:142ee8b12fef 975 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 976 }else{
nyatla 0:142ee8b12fef 977 //再送信処理
nyatla 0:142ee8b12fef 978 rp=i_inst->txbuf.rp;
nyatla 0:142ee8b12fef 979 NyLPC_cStopwatch_set(&sw,q[rp].tick_of_sent);
nyatla 0:142ee8b12fef 980 if(NyLPC_cStopwatch_elapseInMsec(&sw)>q[rp].rto32){
nyatla 0:142ee8b12fef 981 //最古のパケットの送信時間をチェックして、タイムアウトが発生したら、再送時間と送信時刻をセット
nyatla 0:142ee8b12fef 982 //最古パケットRTOを2倍。
nyatla 0:142ee8b12fef 983 q[rp].rto32*=2;
nyatla 0:142ee8b12fef 984 for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
nyatla 0:142ee8b12fef 985 q[i].tick_of_sent=now;
nyatla 0:142ee8b12fef 986 }
nyatla 0:142ee8b12fef 987 if(q[rp].rto32>UIP_IP_RTO_MAX_RTO){
nyatla 0:142ee8b12fef 988 //最古のRTOが64秒を超えたら、CLOSED
nyatla 0:142ee8b12fef 989 i_inst->tcpstateflags =UIP_CLOSED;
nyatla 0:142ee8b12fef 990 resetTxQWithUnlock(i_inst);
nyatla 0:142ee8b12fef 991 sendRst(i_inst);
nyatla 0:142ee8b12fef 992 }else{
nyatla 0:142ee8b12fef 993 //規定時間内なら、再送処理
nyatla 0:142ee8b12fef 994 for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
nyatla 0:142ee8b12fef 995 NyLPC_cUipService_sendIPv4Tx(NyLPC_cIPv4Payload_getBuf(&(q[i].data)));
nyatla 0:142ee8b12fef 996 }
nyatla 0:142ee8b12fef 997 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 998 }
nyatla 0:142ee8b12fef 999 }else{
nyatla 0:142ee8b12fef 1000 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 1001 }
nyatla 0:142ee8b12fef 1002 }
nyatla 0:142ee8b12fef 1003 NyLPC_cStopwatch_finalize(&sw);
nyatla 0:142ee8b12fef 1004 return;
nyatla 0:142ee8b12fef 1005 }
nyatla 0:142ee8b12fef 1006
nyatla 0:142ee8b12fef 1007
nyatla 0:142ee8b12fef 1008 /**
nyatla 0:142ee8b12fef 1009 * この関数は、rxパケットを処理して、ソケットの状態を更新します。
nyatla 0:142ee8b12fef 1010 * uipサービスタスクが実行する関数です。
nyatla 0:142ee8b12fef 1011 * o_ippのペイロードに、応答ペイロードを設定することがあります。
nyatla 0:142ee8b12fef 1012 * この関数はNyLPC_cTcpSocket_periodicと排他実行すること。
nyatla 0:142ee8b12fef 1013 */
nyatla 0:142ee8b12fef 1014 NyLPC_TBool NyLPC_cTcpSocket_parseRx(
nyatla 0:142ee8b12fef 1015 NyLPC_TcTcpSocket_t* i_inst,
nyatla 0:142ee8b12fef 1016 NyLPC_TcIPv4Payload_t* o_ipp)
nyatla 0:142ee8b12fef 1017 {
nyatla 0:142ee8b12fef 1018 int i,s;
nyatla 0:142ee8b12fef 1019 NyLPC_TUInt16 tmp16;
nyatla 0:142ee8b12fef 1020 NyLPC_TUInt16 data_size;
nyatla 0:142ee8b12fef 1021 NyLPC_TUInt8 in_tcpflag=o_ipp->payload.tcp->flags;
nyatla 0:142ee8b12fef 1022 void* tcp_data_offset;
nyatla 0:142ee8b12fef 1023 NyLPC_TBool is_new_packet;
nyatla 0:142ee8b12fef 1024 int num_of_noack;
nyatla 0:142ee8b12fef 1025 void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
nyatla 0:142ee8b12fef 1026 NyLPC_TBool ret;
nyatla 0:142ee8b12fef 1027
nyatla 0:142ee8b12fef 1028 //パラメータの計算
nyatla 0:142ee8b12fef 1029
nyatla 0:142ee8b12fef 1030 tmp16=NyLPC_TTcpHeader_getHeaderLength(o_ipp->payload.tcp);
nyatla 0:142ee8b12fef 1031 //TCPペイロードの長さは、IPパケットの長さ-(IPヘッダ+TCPヘッダ)
nyatla 0:142ee8b12fef 1032 data_size=NyLPC_TIPv4Header_getPacketLength(o_ipp->header)-NyLPC_TIPv4Header_getHeaderLength(o_ipp->header)-tmp16;
nyatla 0:142ee8b12fef 1033 //TCPデータオフセット
nyatla 0:142ee8b12fef 1034 tcp_data_offset=o_ipp->payload.rawbuf+tmp16;
nyatla 0:142ee8b12fef 1035
nyatla 0:142ee8b12fef 1036 //インスタンスをロックする。
nyatla 0:142ee8b12fef 1037 NyLPC_cMutex_lock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 1038
nyatla 0:142ee8b12fef 1039 //RSTのチェック。RST受信時は、状態にかかわらず、CLOSEDステータスに移行する。
nyatla 0:142ee8b12fef 1040 if (in_tcpflag & TCP_RST)
nyatla 0:142ee8b12fef 1041 {
nyatla 0:142ee8b12fef 1042 i_inst->tcpstateflags =UIP_CLOSED;
nyatla 0:142ee8b12fef 1043 goto DROP;
nyatla 0:142ee8b12fef 1044 }
nyatla 0:142ee8b12fef 1045
nyatla 0:142ee8b12fef 1046
nyatla 0:142ee8b12fef 1047 is_new_packet=NyLPC_ntohl(o_ipp->payload.tcp->seqno32)==i_inst->uip_connr.rcv_nxt32;
nyatla 0:142ee8b12fef 1048
nyatla 0:142ee8b12fef 1049
nyatla 0:142ee8b12fef 1050 //OPTIONの反映
nyatla 0:142ee8b12fef 1051
nyatla 0:142ee8b12fef 1052 //MSSの取得
nyatla 0:142ee8b12fef 1053 if(NyLPC_TTcpHeader_getTcpMmsOpt(o_ipp->payload.tcp,&tmp16)){
nyatla 0:142ee8b12fef 1054 //取得で着たら更新
nyatla 0:142ee8b12fef 1055 i_inst->uip_connr.peer_mss=tmp16;
nyatla 0:142ee8b12fef 1056 }
nyatla 0:142ee8b12fef 1057 //受信パケットを元に、未ACKパケットの数を計算
nyatla 0:142ee8b12fef 1058 num_of_noack=getNumOfSending(i_inst,o_ipp->payload.tcp->ackno32);//i_inst->txbuf.num_of_txq;
nyatla 0:142ee8b12fef 1059
nyatla 0:142ee8b12fef 1060 //ステータス毎のACK応答
nyatla 0:142ee8b12fef 1061 switch(i_inst->tcpstateflags)
nyatla 0:142ee8b12fef 1062 {
nyatla 0:142ee8b12fef 1063 case UIP_SYN_RCVD:
nyatla 0:142ee8b12fef 1064 //ACKを受信したら、ESTABLISHEDへ。
nyatla 0:142ee8b12fef 1065 //すべてのパケットをACKしたかで判定。()
nyatla 0:142ee8b12fef 1066 if(num_of_noack==0){
nyatla 0:142ee8b12fef 1067 i_inst->tcpstateflags=UIP_ESTABLISHED;
nyatla 0:142ee8b12fef 1068 }else{
nyatla 0:142ee8b12fef 1069 //それ以外のパケットはドロップする。
nyatla 0:142ee8b12fef 1070 break;//goto DROP;
nyatla 0:142ee8b12fef 1071 }
nyatla 0:142ee8b12fef 1072 //新しいパケットがなければ、無応答
nyatla 0:142ee8b12fef 1073 if(!is_new_packet){
nyatla 0:142ee8b12fef 1074 break;//goto DROP;
nyatla 0:142ee8b12fef 1075 }
nyatla 0:142ee8b12fef 1076 //引き続き、ESTABLISHEDの処理へ。
nyatla 0:142ee8b12fef 1077 case UIP_ESTABLISHED:
nyatla 0:142ee8b12fef 1078 if(data_size>0){
nyatla 0:142ee8b12fef 1079 if(is_new_packet){
nyatla 0:142ee8b12fef 1080 if(addRecvData(i_inst,tcp_data_offset,data_size)){
nyatla 0:142ee8b12fef 1081 //通常のACK返却
nyatla 0:142ee8b12fef 1082 i_inst->uip_connr.rcv_nxt32+=data_size;
nyatla 0:142ee8b12fef 1083 }else{
nyatla 0:142ee8b12fef 1084 //失敗したときは必要に応じて単純ACK
nyatla 0:142ee8b12fef 1085 }
nyatla 0:142ee8b12fef 1086 }
nyatla 0:142ee8b12fef 1087 }
nyatla 0:142ee8b12fef 1088 //MSSとWNDの更新
nyatla 0:142ee8b12fef 1089 i_inst->uip_connr.peer_mss = i_inst->uip_connr.default_mss;
nyatla 0:142ee8b12fef 1090 //どちらにしろ、ACK送信
nyatla 0:142ee8b12fef 1091 if(is_new_packet && (in_tcpflag & TCP_FIN)){
nyatla 0:142ee8b12fef 1092 //FINがあるときは、ステータスをCLOSE_WAITへセットして、ACKを返す。
nyatla 0:142ee8b12fef 1093 i_inst->tcpstateflags = UIP_CLOSE_WAIT;
nyatla 0:142ee8b12fef 1094 i_inst->uip_connr.rcv_nxt32++;
nyatla 0:142ee8b12fef 1095 }
nyatla 0:142ee8b12fef 1096 break;
nyatla 0:142ee8b12fef 1097 case UIP_CLOSE_WAIT:
nyatla 0:142ee8b12fef 1098 //必要に応じたACK応答
nyatla 0:142ee8b12fef 1099 break;
nyatla 0:142ee8b12fef 1100 case UIP_LAST_ACK:
nyatla 0:142ee8b12fef 1101 //ACK(by FIN)が得られたなら、CLOSEDへ。
nyatla 0:142ee8b12fef 1102 if(num_of_noack==0){
nyatla 0:142ee8b12fef 1103 i_inst->tcpstateflags=UIP_CLOSED;
nyatla 0:142ee8b12fef 1104 }
nyatla 0:142ee8b12fef 1105 //必要に応じたACK応答
nyatla 0:142ee8b12fef 1106 break;
nyatla 0:142ee8b12fef 1107 case UIP_FIN_WAIT_1:
nyatla 0:142ee8b12fef 1108 //FIN受信->CLOSINGへ
nyatla 0:142ee8b12fef 1109 if(is_new_packet && (in_tcpflag & TCP_FIN)){
nyatla 0:142ee8b12fef 1110 i_inst->uip_connr.rcv_nxt32++;
nyatla 0:142ee8b12fef 1111 if(num_of_noack==0){
nyatla 0:142ee8b12fef 1112 //FINとACKを受信
nyatla 0:142ee8b12fef 1113 i_inst->tcpstateflags=UIP_TIME_WAIT;
nyatla 0:142ee8b12fef 1114 }else{
nyatla 0:142ee8b12fef 1115 //FINのみ
nyatla 0:142ee8b12fef 1116 i_inst->tcpstateflags=UIP_CLOSING;
nyatla 0:142ee8b12fef 1117 }
nyatla 0:142ee8b12fef 1118 }else if(num_of_noack==0){
nyatla 0:142ee8b12fef 1119 //ACKのみ
nyatla 0:142ee8b12fef 1120 i_inst->tcpstateflags=UIP_FIN_WAIT_2;
nyatla 0:142ee8b12fef 1121 }
nyatla 0:142ee8b12fef 1122 //必要に応じたACK応答
nyatla 0:142ee8b12fef 1123 break;
nyatla 0:142ee8b12fef 1124 case UIP_FIN_WAIT_2:
nyatla 0:142ee8b12fef 1125 //FIN受信->TIME_WAITへ(pureACK)
nyatla 0:142ee8b12fef 1126 if(is_new_packet && (in_tcpflag & TCP_FIN)){
nyatla 0:142ee8b12fef 1127 i_inst->uip_connr.rcv_nxt32++;
nyatla 0:142ee8b12fef 1128 i_inst->tcpstateflags=UIP_TIME_WAIT;
nyatla 0:142ee8b12fef 1129 }
nyatla 0:142ee8b12fef 1130 break;
nyatla 0:142ee8b12fef 1131 case UIP_CLOSING:
nyatla 0:142ee8b12fef 1132 //ACK受信したら、TIME_WAITへ
nyatla 0:142ee8b12fef 1133 if(num_of_noack==0){
nyatla 0:142ee8b12fef 1134 i_inst->tcpstateflags=UIP_TIME_WAIT;
nyatla 0:142ee8b12fef 1135 }
nyatla 0:142ee8b12fef 1136 break;
nyatla 0:142ee8b12fef 1137 case UIP_CLOSED:
nyatla 0:142ee8b12fef 1138 //何もできない。何もしない。
nyatla 0:142ee8b12fef 1139 break;//goto DROP;
nyatla 0:142ee8b12fef 1140 case UIP_TIME_WAIT:
nyatla 0:142ee8b12fef 1141 //最終ACKを送り続ける。
nyatla 0:142ee8b12fef 1142 break;
nyatla 0:142ee8b12fef 1143 default:
nyatla 0:142ee8b12fef 1144 goto DROP;
nyatla 0:142ee8b12fef 1145 }
nyatla 0:142ee8b12fef 1146 //ウインドウサイズを更新
nyatla 0:142ee8b12fef 1147 i_inst->uip_connr.peer_win=NyLPC_ntohs(o_ipp->payload.tcp->wnd16);
nyatla 0:142ee8b12fef 1148
nyatla 0:142ee8b12fef 1149 //送信キューから、Peerが受信したデータを削除する。
nyatla 0:142ee8b12fef 1150 if(in_tcpflag & TCP_ACK){
nyatla 0:142ee8b12fef 1151 //再送パケットキューから送信済みのデータを回収(後で開放)
nyatla 0:142ee8b12fef 1152 NyLPC_Trace();
nyatla 0:142ee8b12fef 1153 s=updateTxQByIndex(i_inst,o_ipp->payload.tcp->ackno32,dlist);
nyatla 0:142ee8b12fef 1154 NyLPC_Trace();
nyatla 0:142ee8b12fef 1155 }else{
nyatla 0:142ee8b12fef 1156 s=0;
nyatla 0:142ee8b12fef 1157 }
nyatla 0:142ee8b12fef 1158 //新しいパケットがきた場合は、再送キューのACKを更新する。
nyatla 0:142ee8b12fef 1159 if(is_new_packet){
nyatla 0:142ee8b12fef 1160 //再送キューのACKを更新
nyatla 0:142ee8b12fef 1161 updateTxAck(i_inst,NyLPC_htonl(i_inst->uip_connr.rcv_nxt32));
nyatla 0:142ee8b12fef 1162 }
nyatla 0:142ee8b12fef 1163
nyatla 0:142ee8b12fef 1164 //送信キューのない
nyatla 0:142ee8b12fef 1165 ret=NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 1166 if(((in_tcpflag&(TCP_FIN|TCP_SYN))!=0x00) ||
nyatla 0:142ee8b12fef 1167 ((!is_new_packet) && (data_size>0)))
nyatla 0:142ee8b12fef 1168 {
nyatla 0:142ee8b12fef 1169 setPacket(i_inst,o_ipp,TCP_ACK,NULL,0);
nyatla 0:142ee8b12fef 1170 ret=NyLPC_TBool_TRUE;
nyatla 0:142ee8b12fef 1171 }else{
nyatla 0:142ee8b12fef 1172 ret=NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 1173 }
nyatla 0:142ee8b12fef 1174 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 1175 //取り外したTXメモリの開放
nyatla 0:142ee8b12fef 1176 for(i=0;i<s;i++){
nyatla 0:142ee8b12fef 1177 //取り外したTXメモリを開放
nyatla 0:142ee8b12fef 1178 NyLPC_cUipService_releaseTxBuf(dlist[i]);
nyatla 0:142ee8b12fef 1179 }
nyatla 0:142ee8b12fef 1180 NyLPC_Trace();
nyatla 0:142ee8b12fef 1181 return ret;
nyatla 0:142ee8b12fef 1182 DROP:
nyatla 0:142ee8b12fef 1183 //ACKしたパケットを送信キューから削除
nyatla 0:142ee8b12fef 1184 NyLPC_cMutex_unlock(&(i_inst->_smutex));
nyatla 0:142ee8b12fef 1185 NyLPC_Trace();
nyatla 0:142ee8b12fef 1186 return NyLPC_TBool_FALSE;
nyatla 0:142ee8b12fef 1187 }
nyatla 0:142ee8b12fef 1188
nyatla 0:142ee8b12fef 1189
nyatla 0:142ee8b12fef 1190
nyatla 0:142ee8b12fef 1191
nyatla 0:142ee8b12fef 1192
nyatla 0:142ee8b12fef 1193