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:
Fri Sep 13 06:38:16 2013 +0000
Revision:
57:bc4330dfa62f
Parent:
43:a182f2b5ff41
Child:
58:03b89038b21a
update mimic core r329;

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