Ryo Iizuka / libMiMic

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

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

Who changed what in which revision?

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