Ryo Iizuka / libMiMic

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

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