Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
core/uip/NyLPC_cTcpSocket.c@12:efe841863fc8, 2013-04-20 (annotated)
- Committer:
- nyatla
- Date:
- Sat Apr 20 05:03:57 2013 +0000
- Revision:
- 12:efe841863fc8
- Parent:
- core/uip/NyLPC_cTcpSocket.cpp@2:b96c1e90d120
- Child:
- 20:3b0b444b4deb
MiMic r218
Who changed what in which revision?
| User | Revision | Line number | New 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 | 2:b96c1e90d120 | 317 | void NyLPC_cTcpSocket_finalize(NyLPC_TcTcpSocket_t* i_inst) |
| 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 |
MiMic Webservice library