This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NyLPC_cMiMicIpTcpSocket.c Source File

NyLPC_cMiMicIpTcpSocket.c

00001 /*********************************************************************************
00002  * PROJECT: MiMic
00003  * --------------------------------------------------------------------------------
00004  *
00005  * This file is part of MiMic
00006  * Copyright (C)2011 Ryo Iizuka
00007  *
00008  * MiMic is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU Lesser General Public License as published
00010  * by the Free Software Foundation, either version 3 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public License
00019  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020  *
00021  * For further information please contact.
00022  *  http://nyatla.jp/
00023  *  <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
00024  *
00025  *********************************************************************************/
00026 #include "NyLPC_cMiMicIpTcpSocket_protected.h"
00027 #include "NyLPC_stdlib.h"
00028 #include "NyLPC_cMiMicIpNetIf_protected.h"
00029 
00030 
00031 static NyLPC_TUInt32 iss32=3939;
00032 #define SIZE_OF_IPv4_TCPIP_HEADER 40
00033 
00034 /**
00035  * TCPのRTOの最大値。
00036  * ms単位である。
00037  * defaultは64SEC
00038  */
00039 #define UIP_IP_RTO_MAX_RTO 64000
00040 /**
00041  * TCPのRTOの初期値。
00042  * ms単位である。
00043  * 伝送路の特性に合わせて調整すること。
00044  */
00045 #define UIP_TCP_RTO_INITIAL 3000
00046 
00047 /**
00048  * CONNECTION時のRTO
00049  */
00050 #define UIP_TCP_RTO_CONNECTION_INITIAL 200
00051 
00052 /**
00053  * 下限値
00054  */
00055 #define UIP_TCP_RTO_MINIMUM 100
00056 
00057 
00058 /**
00059  * for Debug
00060  * RTOの情報をログ領域に取る。
00061  */
00062 #ifdef RTO_LOG
00063     NyLPC_TUInt32 rto_log[256];
00064     int rto_log_st=0;
00065     #define DEBUG_RTO_LOG(i_inst) if(rto_log_st<256){rto_log[rto_log_st++]=i_inst->uip_connr.current_rto32;};
00066 #else
00067     #define DEBUG_RTO_LOG(i_inst)
00068 #endif
00069 
00070 //#define lockResource(i_inst) NyLPC_cMutex_lock(&((i_inst)->_smutex))
00071 //#define unlockResource(i_inst) NyLPC_cMutex_unlock(&((i_inst)->_smutex))
00072 #define lockResource(i_inst) NyLPC_cMutex_lock(NyLPC_cIPv4_getSockMutex(((i_inst)->_parent_ipv4)))
00073 #define unlockResource(i_inst) NyLPC_cMutex_unlock(NyLPC_cIPv4_getSockMutex(((i_inst)->_parent_ipv4)))
00074 
00075 static void sendRst(NyLPC_TcMiMicIpTcpSocket_t* i_inst);
00076 
00077 
00078 
00079 
00080 ////////////////////////////////////////////////////////////////////////////////////////////////////
00081 //
00082 //  Packet writer
00083 //
00084 ////////////////////////////////////////////////////////////////////////////////////////////////////
00085 
00086 
00087 /**
00088  * TCPヘッダに値をセットする。checksum,wndは0初期化する。
00089  */
00090 static void setTcpTxHeader(struct NyLPC_TTcpHeader* i_struct,NyLPC_TUInt8 i_flag,const struct uip_conn* i_conn)
00091 {
00092     i_struct->flags    = i_flag;
00093     //sorce & destination port
00094     i_struct->srcport  = i_conn->lport;
00095     i_struct->destport = i_conn->rport;
00096     //ACK number
00097     i_struct->ackno32  = NyLPC_htonl(i_conn->rcv_nxt32);
00098     //Seq Number
00099     i_struct->seqno32  = NyLPC_htonl(i_conn->snd_nxt32);
00100     //uip_func_tcp_send_noconn(BUF);
00101     i_struct->urgp[0]  = i_struct->urgp[1] = 0;
00102     i_struct->tcpchksum= 0;
00103 }
00104 
00105 static void setTxPacket(const NyLPC_TcMiMicIpTcpSocket_t* i_inst,void* i_tx_buf,NyLPC_TUInt8 i_tcpf,const void* i_buf,NyLPC_TUInt16 i_len)
00106 {
00107     struct NyLPC_TIPv4Header*   iph;
00108     struct NyLPC_TTcpHeader*    tcph;
00109     NyLPC_TUInt8 iph_word=0x05;
00110     NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
00111     //IPヘッダの更新
00112     iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
00113     iph->vhl=0x40|(0x0f&iph_word);
00114     iph->destipaddr=i_inst->uip_connr.ripaddr;
00115     iph->srcipaddr =*(i_inst->uip_connr.lipaddr);
00116     NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
00117     //TCPヘッダの更新
00118     tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
00119 
00120 
00121     //SYNが有るならMSSの書き込み
00122     if((TCP_SYN & i_tcpf)){
00123         tcph_word+=((TCP_OPT_MSS_LEN) / 4);
00124         NyLPC_TTcpHeader_setMmsOpt(((NyLPC_TUInt8*)(tcph+1)),i_inst->uip_connr.default_mss);
00125     }
00126     tcph->tcpoffset=(tcph_word<<4);
00127     setTcpTxHeader(tcph,i_tcpf,&(i_inst->uip_connr));
00128 
00129     //最終的なパケットサイズと必要ならペイロードを書き込み
00130     if(i_buf!=NULL){
00131         iph->len16=NyLPC_htons(i_len+(iph_word+tcph_word)*4);
00132         memcpy(((NyLPC_TUInt8*)i_tx_buf)+((iph_word+tcph_word)*4),i_buf,i_len);
00133     }else{
00134         iph->len16=NyLPC_htons((iph_word+tcph_word)*4);
00135     }
00136     //WND設定
00137     tcph->wnd16=NyLPC_htons(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf)));
00138     //Checksumの生成
00139     tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
00140     iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
00141     return;
00142 }
00143 
00144 /**
00145  * IP/TCPヘッダが40バイト固定として、i_tx_buf+40の位置にあるペイロードに対するIP/TCPヘッダを書き込みます。
00146  */
00147 static void setTxPacketHeader(const NyLPC_TcMiMicIpTcpSocket_t* i_inst,void* i_tx_buf,NyLPC_TUInt8 i_tcpf,NyLPC_TUInt16 i_len)
00148 {
00149     struct NyLPC_TIPv4Header*   iph;
00150     struct NyLPC_TTcpHeader*    tcph;
00151     NyLPC_TUInt8 iph_word=0x05;
00152     NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
00153     //IPヘッダの更新
00154     iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
00155     iph->vhl=0x40|(0x0f&iph_word);
00156     iph->destipaddr=i_inst->uip_connr.ripaddr;
00157     iph->srcipaddr =*(i_inst->uip_connr.lipaddr);
00158     NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
00159 
00160     //TCPヘッダの更新
00161     tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
00162     tcph->tcpoffset=(tcph_word<<4);
00163     setTcpTxHeader(tcph,i_tcpf,&(i_inst->uip_connr));
00164 
00165     //最終的なパケットサイズと必要ならペイロードを書き込み
00166     iph->len16=NyLPC_htons(i_len+(iph_word+tcph_word)*4);
00167     //WND設定
00168     tcph->wnd16=NyLPC_htons(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf)));
00169     //Checksumの生成
00170     tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
00171     iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
00172     return;
00173 }
00174 
00175 
00176 
00177 
00178 
00179 ////////////////////////////////////////////////////////////////////////////////////////////////////
00180 //
00181 //  Mainclass::private
00182 //
00183 ////////////////////////////////////////////////////////////////////////////////////////////////////
00184 
00185 /**
00186  * ACK番号を更新する。
00187  * @param i_ackno
00188  * ネットワークオーダーのACK番号
00189  */
00190 static void updateAckNo(void* i_tx_buf,NyLPC_TUInt32 i_ackno)
00191 {
00192     struct NyLPC_TIPv4Header*   iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
00193     struct NyLPC_TTcpHeader*    tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
00194 
00195 /*  union{
00196         NyLPC_TUInt32 l;
00197         NyLPC_TUInt8 b[4];
00198     }old_ack,new_ack;
00199     NyLPC_TUInt16 v1;
00200     //checksumの計算
00201     old_ack.l=i_inst->payload.tcp->ackno32;//古いACK番号
00202     new_ack.l=i_ackno;//新しいACK番号
00203     v1=NyLPC_ntohs(~(i_inst->payload.tcp->tcpchksum));//1の補数を取って、ホストオーダーに戻す。
00204     //減算
00205     v1=sub16c(v1,(old_ack.b[0]<<8)+old_ack.b[1]);
00206     v1=sub16c(v1,(old_ack.b[2]<<8)+old_ack.b[3]);
00207     //加算
00208     v1=add16c(v1,(new_ack.b[0]<<8)+new_ack.b[1]);
00209     v1=add16c(v1,(new_ack.b[2]<<8)+new_ack.b[3]);
00210     v1=~NyLPC_htons(v1);*/
00211 NyLPC_Trace();
00212     tcph->ackno32=i_ackno;
00213 NyLPC_Trace();
00214     tcph->tcpchksum = 0;
00215 NyLPC_Trace();
00216     tcph->tcpchksum = ~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
00217 NyLPC_Trace();
00218 
00219 /*
00220     if((i_inst->payload.tcp->tcpchksum!=v1)){
00221         NyLPC_Warning();
00222     }*/
00223 }
00224 
00225 
00226 
00227 /**
00228  * 指定した送信パケットがACK済であるか調べる。
00229  */
00230 static NyLPC_TBool isPacketAcked(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq)
00231 {
00232     int rp;
00233     struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
00234     rp=i_inst->txbuf.rp;
00235     while(rp!=i_inst->txbuf.wp){
00236         if(q[rp].ackno==i_sq){
00237             return NyLPC_TBool_FALSE;
00238         }
00239         rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
00240     }
00241     return NyLPC_TBool_TRUE;
00242 }
00243 /**
00244  * 送信キューからi_sq以前に送信したパケットを除外して、残り個数を返却する。
00245  */
00246 static int getNumOfSending(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq)
00247 {
00248     int rp,n;
00249     struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
00250     rp=i_inst->txbuf.rp;
00251     n=0;
00252     while(rp!=i_inst->txbuf.wp){
00253         if(q[rp].ackno==i_sq){
00254             return n;
00255         }
00256         n++;
00257         rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
00258     }
00259     return n;
00260 }
00261 /**
00262  * この関数は、コネクションをリセットします。
00263  * ロック状態でコールしてください。
00264  * 関数は、現在バッファにある再送信待ちデータを開放します。
00265  */
00266 static void resetTxQWithUnlock(NyLPC_TcMiMicIpTcpSocket_t* i_inst)
00267 {
00268     int i,l;
00269     struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
00270     void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
00271 
00272     l=0;
00273     while(i_inst->txbuf.rp!=i_inst->txbuf.wp){
00274         dlist[l]=q[i_inst->txbuf.rp].packet;
00275         l++;
00276         i_inst->txbuf.rp=(i_inst->txbuf.rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
00277     }
00278     i_inst->txbuf.rp=i_inst->txbuf.wp=0;
00279     //ロック解除
00280     unlockResource(i_inst);
00281     //セーブしたバッファを開放
00282     for(i=0;i<l;i++){
00283         NyLPC_cMiMicIpNetIf_releaseTxBuf(dlist[i]);
00284     }
00285     return;
00286 }
00287 /**
00288  * TXバッファの再送パケットのACK番号を更新します。
00289  * ロックして実行してください。
00290  * @param i_ackno
00291  * ネットワークオーダーのACK番号
00292  */
00293 static void updateTxAck(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TUInt32 i_ackno)
00294 {
00295     NyLPC_TUInt8 rp;
00296     struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
00297     NyLPC_ArgAssert(i_inst!=NULL);
00298     rp=i_inst->txbuf.rp;
00299     while(rp!=i_inst->txbuf.wp){
00300         updateAckNo(q[rp].packet,i_ackno);
00301         rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
00302     }
00303 }
00304 
00305 /**
00306  * RTOの予測関数
00307  */
00308 static void estimateRTO(NyLPC_TcMiMicIpTcpSocket_t* i_inst,int s,int n)
00309 {
00310     NyLPC_TcStopwatch_t sw;
00311     NyLPC_TUInt32 cr_rtt_min,cr_rtt_max,sk_rto,new_rto,w;
00312     int i;
00313     struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
00314     NyLPC_cStopwatch_initialize(&sw);
00315 
00316     sk_rto=i_inst->uip_connr.current_rto32;
00317     //ACKされたパケットの個数は?
00318     switch(n){
00319     case 1:
00320         NyLPC_cStopwatch_set(&sw,q[s].tick_of_sent);
00321         cr_rtt_min=NyLPC_cStopwatch_elapseInMsec(&sw);
00322         if(sk_rto<cr_rtt_min){
00323             //現在のRTOよりも大きい→再送があった。(再送の理由が回線遅延によるものかわからないので、基本RTOを25%増やす。)
00324             new_rto=sk_rto*10/8;
00325         }else if(sk_rto/4<cr_rtt_min){
00326             //現在のRTOの1/4< n < 現在のRTO 想定内の変動。1/8
00327             new_rto=(sk_rto+(cr_rtt_min*3*7))/8;
00328         }else{
00329             //現在の1/4以下。RTOを再計算。 RTOが大きすぎるので再計算。(計測値を優先した現在値との平均値)
00330             new_rto=(sk_rto+(cr_rtt_min*3*3))/4;
00331         }
00332         break;
00333     default:
00334         //複数のパケットなら、最大と最小の時刻を得る。
00335         NyLPC_cStopwatch_set(&sw,q[s].tick_of_sent);
00336         cr_rtt_min=cr_rtt_max=NyLPC_cStopwatch_elapseInMsec(&sw);
00337         for(i=1;i<n;i++){
00338             NyLPC_cStopwatch_set(&sw,q[(s+i)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ].tick_of_sent);
00339             w=NyLPC_cStopwatch_elapseInMsec(&sw);
00340             if(cr_rtt_min>w){
00341                 cr_rtt_min=w;
00342             }
00343             if(cr_rtt_max<w){
00344                 cr_rtt_max=w;
00345             }
00346         }
00347         if(sk_rto<cr_rtt_min && sk_rto<cr_rtt_max){
00348             //最大値,最小値とも現在のRTTより大きい→低速な回線を検出。
00349             new_rto=cr_rtt_max*10/8;//最大経過時間の25%増しの時間を設定。
00350         }else if(sk_rto/4<cr_rtt_min){
00351             //現在のRTOの1/4< n < 現在のRTO 想定範囲内。1/8の加重平均で速度計算。
00352             new_rto=(sk_rto+(cr_rtt_min*3*7))/8;
00353         }else{
00354             //現在の1/4以下。RTOが大きすぎるので再計算。(計測値を優先した加重平均)
00355             new_rto=(sk_rto+(cr_rtt_min*3*3))/4;
00356         }
00357         break;
00358     }
00359     NyLPC_cStopwatch_finalize(&sw);
00360     if(new_rto<UIP_TCP_RTO_MINIMUM){
00361         new_rto=UIP_TCP_RTO_MINIMUM;
00362     }
00363     i_inst->uip_connr.current_rto32=new_rto;
00364 }
00365 
00366 /**
00367  * TXキューから、入力されたシーケンス番号より前のパケットを除外します。
00368  * リングバッファのrp->wp-1までをチェックして、sqに等しいi_sq以前のパケットバッファをo_dlistへ返します。
00369  *
00370  */
00371 static int updateTxQByIndex(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,void* o_dlist[])
00372 {
00373     int rp,n;
00374     struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
00375     //ロック状態なう
00376     rp=i_inst->txbuf.rp;
00377     n=0;
00378     //This is debug
00379     DEBUG_RTO_LOG(i_inst);
00380 
00381     while(rp!=i_inst->txbuf.wp){
00382         o_dlist[n]=q[rp].packet;
00383         if(q[rp].ackno==i_sq){
00384             //i_inst->txbuf.rp->rpのパケットのRTOからbaseRTOの値を再計算。
00385             estimateRTO(i_inst,i_inst->txbuf.rp,n+1);
00386             i_inst->txbuf.rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
00387             return n+1;
00388         }
00389         n++;
00390         rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
00391     }
00392     return 0;
00393 }
00394 
00395 
00396 
00397 /**
00398  * 空きキューを1個返します。
00399  * 空きキューの
00400  */
00401 static struct NyLPC_TcTcpSocket_TxQItem* getTxQ(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TcStopwatch_t* i_timer)
00402 {
00403     int i;
00404     struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
00405     do{
00406         //クローズドに遷移してしまったら、エラーである。
00407         if(i_inst->tcpstateflags==UIP_CLOSED){
00408             return NULL;
00409         }
00410         //キューの空きをチェック。wp+1==rpなら、キューがいっぱい。rp==wpなら、キューが空。
00411         if(((i_inst->txbuf.wp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ)==i_inst->txbuf.rp){
00412             //一時的なアンロック
00413             unlockResource(i_inst);
00414             //タスクスイッチ
00415             NyLPC_cThread_yield();
00416             //ロック
00417             lockResource(i_inst);
00418             continue;
00419         }
00420         i=i_inst->txbuf.wp;
00421         i_inst->txbuf.wp=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
00422         return &(q[i]);
00423     }while(!NyLPC_cStopwatch_isExpired(i_timer));
00424     //失敗。タイムアウト。
00425     return NULL;
00426 }
00427 
00428 
00429 
00430 
00431 
00432 
00433 /**********************************************************************
00434  * public 関数
00435  **********************************************************************/
00436 static const struct NyLPC_TIPv4Addr* getPeerAddr(const NyLPC_TiTcpSocket_t* i_inst);
00437 static NyLPC_TUInt16 getPeerPort(const NyLPC_TiTcpSocket_t* i_inst);
00438 static NyLPC_TBool accept(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec);
00439 static NyLPC_TInt32 precv(NyLPC_TiTcpSocket_t* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec);
00440 static void pseek(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt16 i_seek);
00441 static NyLPC_TInt32 send(NyLPC_TiTcpSocket_t* i_inst,const void* i_buf_ptr,NyLPC_TInt32 i_len,NyLPC_TUInt32 i_wait_in_msec);
00442 static void close(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec);
00443 static void* allocSendBuf(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_buf_size,NyLPC_TUInt32 i_wait_in_msec);
00444 static void releaseSendBuf(NyLPC_TiTcpSocket_t* i_inst,void* i_buf_ptr);
00445 static NyLPC_TBool psend(NyLPC_TiTcpSocket_t* i_inst,void* i_buf_ptr,int i_len,NyLPC_TUInt32 i_wait_in_msec);
00446 static NyLPC_TBool connect(NyLPC_TiTcpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_peer_port,NyLPC_TUInt32 i_wait_in_msec);
00447 static void finalize(NyLPC_TiTcpSocket_t* i_inst);
00448 
00449 const static struct NyLPC_TiTcpSocket_Interface _interface=
00450 {
00451     getPeerAddr,
00452     getPeerPort,
00453     accept,
00454     precv,
00455     pseek,
00456     send,
00457     close,
00458     allocSendBuf,
00459     releaseSendBuf,
00460     psend,
00461     connect,
00462     finalize
00463 };
00464 
00465 static const struct NyLPC_TIPv4Addr* getPeerAddr(const NyLPC_TiTcpSocket_t* i_inst)
00466 {
00467     const NyLPC_TcMiMicIpTcpSocket_t* inst=(const NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
00468     return &inst->uip_connr.ripaddr;
00469 }
00470 static NyLPC_TUInt16 getPeerPort(const NyLPC_TiTcpSocket_t* i_inst)
00471 {
00472     const NyLPC_TcMiMicIpTcpSocket_t* inst=(const NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
00473     return inst->uip_connr.rport;
00474 }
00475 
00476 
00477 
00478 
00479 NyLPC_TBool NyLPC_cMiMicIpTcpSocket_initialize(NyLPC_TcMiMicIpTcpSocket_t* i_inst,void* i_rbuf,NyLPC_TUInt16 i_rbuf_len)
00480 {
00481     int i;
00482     NyLPC_TcMiMicIpNetIf_t* srv=_NyLPC_TcMiMicIpNetIf_inst;
00483     i_inst->_super._interface=&_interface;
00484     i_inst->_parent_ipv4=&srv->_tcpv4;
00485 
00486     //uipサービスは初期化済であること。
00487     NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService());
00488 
00489     NyLPC_cFifoBuffer_initialize(&(i_inst->rxbuf),i_rbuf,i_rbuf_len);
00490     //  NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(i_inst->_smutex)));//個別Mutex
00491 //  i_inst->_smutex=NyLPC_cIPv4_getSockMutex(&(srv->_tcpv4));//共有Mutex
00492     i_inst->tcpstateflags=UIP_CLOSED;
00493     i_inst->txbuf.rp=i_inst->txbuf.wp=0;
00494     for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
00495         i_inst->txbuf.txq[i].packet=NULL;
00496     }
00497     //管理リストへ登録。
00498     return NyLPC_TBool_TRUE;
00499 }
00500 
00501 
00502 
00503 NyLPC_TBool NyLPC_cMiMicIpTcpSocket_listenSyn(NyLPC_TcMiMicIpTcpSocket_t* i_inst,const struct NyLPC_TTcpSocketSynParam* i_lq,NyLPC_TUInt16 i_lport)
00504 {
00505 //  NyLPC_Assert(NyLPC_cMutex_isLocked(i_inst->_smutex));
00506     lockResource(i_inst);
00507     //ソケットが無効であること。
00508     if(i_inst->tcpstateflags==UIP_CLOSED)
00509     {
00510         //localipとdefault_mmsは別枠で設定
00511         /* Fill in the necessary fields for the new connection. */
00512         i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_INITIAL;
00513         i_inst->uip_connr.lport = i_lport;
00514         i_inst->uip_connr.rport = i_lq->rport;
00515         i_inst->uip_connr.ripaddr=i_lq->srcaddr;
00516         i_inst->uip_connr.snd_nxt32=iss32;
00517         /* rcv_nxt should be the seqno from the incoming packet + 1. */
00518         i_inst->uip_connr.rcv_nxt32= i_lq->rcv_nxt32;
00519         //MSSの設定
00520         i_inst->uip_connr.peer_mss=(i_lq->mss!=0)?i_lq->mss:i_inst->uip_connr.default_mss;
00521         i_inst->uip_connr.peer_win=0;
00522         NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
00523         //ここでステータスがかわる。
00524         i_inst->tcpstateflags = UIP_SYN_RCVD;
00525         //前回のデータが残っていた場合の保険
00526         if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
00527             resetTxQWithUnlock(i_inst);
00528         }else{
00529             unlockResource(i_inst);
00530         }
00531         return NyLPC_TBool_TRUE;
00532     }
00533     unlockResource(i_inst);
00534     return NyLPC_TBool_FALSE;
00535 }
00536 
00537 
00538 /**
00539  * sq番のTxがキューから消え去るのを待ちます。
00540  * この関数は、アンロック状態でコールしてください。
00541  * <div>
00542  * パケットがキューからなくなる条件は、以下の2つです。
00543  * <ul>
00544  * <li>ACKを受信してパケットキューが更新された。</li>
00545  * <li>RSTを受信して(CLOSEDに遷移して)、キューがクリアされた。</li>
00546  * <li>送信タイムアウトで関数が(CLOSEDに遷移させて)キューをクリアした。</li>
00547  * </ul>
00548  * </div>
00549  * @param i_wait_msec
00550  * @return
00551  * 1番目の条件でパケットが消失したときのみ、TRUEを返します。
00552  * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
00553  */
00554 static NyLPC_TBool waitForTxRemove(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,NyLPC_TcStopwatch_t* i_timer)
00555 {
00556     NyLPC_TUInt8 f;
00557     lockResource(i_inst);
00558     do{
00559         //パケットが送信中か調べる。
00560         if(!isPacketAcked(i_inst,i_sq)){
00561             //まだある場合は、タスクスイッチを繰り返して消失を待つ。
00562             unlockResource(i_inst);
00563             NyLPC_cThread_yield();
00564             lockResource(i_inst);
00565             continue;
00566         }
00567         //なくなった場合は、原因を調べる。
00568         f=i_inst->tcpstateflags;
00569         unlockResource(i_inst);
00570         return (f==UIP_CLOSED)?NyLPC_TBool_FALSE:NyLPC_TBool_TRUE;
00571     }while(!NyLPC_cStopwatch_isExpired(i_timer));
00572     unlockResource(i_inst);
00573     return NyLPC_TBool_FALSE;
00574 }
00575 
00576 
00577 /**
00578  * 再送信処理をセットして、パケットを送信します。
00579  * この関数は「アンロック状態で」実行してください。
00580  * @param i_len
00581  * 送信データサイズを指定します。
00582  * この番号は、シーケンス番号の加算値ではありませんので、注意をしてください。
00583  * @return
00584  * <ul>
00585  * <li>n=-1:送信キューへの投入に失敗した。</li>
00586  * <li>n>=0:nバイトのデータを送信キューへの投入することに成功した。</li>
00587  * </ul>
00588  * 送信キューに失敗する理由は2つあります。1つは、TXバッファがフルでタイムアウト。もうひとつは、非同期なコネクリョンのリセットです。
00589  * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
00590  */
00591 static NyLPC_TInt32 sendWithRetransmit(NyLPC_TcMiMicIpTcpSocket_t* i_inst,NyLPC_TUInt8 i_tcpf,const void* i_buf,NyLPC_TUInt16 i_len,NyLPC_TcStopwatch_t* i_timer,NyLPC_TUInt32* o_ack)
00592 {
00593     struct NyLPC_TcTcpSocket_TxQItem* txq;
00594     NyLPC_TUInt16 s;
00595     void* buf;
00596     NyLPC_TUInt32 next_ack;
00597     //送信バッファを取得
00598     //@bug オブションパケット送信時に4バイト足りないメモリ要求しない?問題になってないけど。
00599     for(;;){
00600         buf=NyLPC_cMiMicIpNetIf_allocTxBuf(i_len+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
00601         if(buf!=NULL){
00602             break;
00603         }
00604         //タイムアウト確認
00605         if(NyLPC_cStopwatch_isExpired(i_timer)){
00606             return -1;
00607         }
00608     };
00609     lockResource(i_inst);
00610     //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
00611     if(i_len>0){
00612         while(i_inst->uip_connr.peer_win==0){
00613             unlockResource(i_inst);
00614             //時間切れならエラー。
00615             if(NyLPC_cStopwatch_isExpired(i_timer)){
00616                 return -1;
00617             }
00618             NyLPC_cThread_yield();
00619             lockResource(i_inst);
00620         }
00621     }
00622     //送信キューの取得
00623     txq=getTxQ(i_inst,i_timer);
00624     //送信キューが取れなかった。
00625     if(txq==NULL){
00626         //シーケンス番号をロールバックできないので、エラーとする。
00627         unlockResource(i_inst);
00628         NyLPC_cMiMicIpNetIf_releaseTxBuf(buf);
00629         return -1;
00630     }
00631 
00632     //送信バッファを基準とした送信サイズを計算
00633     s-=SIZE_OF_IPv4_TCPIP_HEADER;
00634     //送信サイズよりMMSが小さければ、送信サイズを修正
00635     if(i_inst->uip_connr.peer_mss<s){
00636         s=i_inst->uip_connr.peer_mss;
00637     }
00638     //送信サイズよりpeerのウインドウサイズが小さければ修正
00639     if(i_inst->uip_connr.peer_win<s){
00640         s=i_inst->uip_connr.peer_win;
00641     }
00642     //送信サイズより、データサイズが小さければ、送信サイズを修正
00643     if(i_len<s){
00644         s=i_len;
00645     }
00646     //ACK番号の計算
00647     next_ack=i_inst->uip_connr.snd_nxt32+s+(((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00)?1:0);
00648     txq->rto32=i_inst->uip_connr.current_rto32;
00649     txq->tick_of_sent=NyLPC_cStopwatch_now();
00650 
00651     //パケットの書き込み
00652     setTxPacket(i_inst,buf,i_tcpf,i_buf,s);
00653     txq->packet=buf;
00654 
00655     //シーケンス番号の更新
00656     i_inst->uip_connr.snd_nxt32=next_ack;
00657     //Peerのウインドウサイズを更新
00658     i_inst->uip_connr.peer_win-=s;
00659     //ACK番号の返却
00660     *o_ack=txq->ackno=NyLPC_HTONL(next_ack);
00661     unlockResource(i_inst);
00662     NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf);
00663     return s;
00664 }
00665 /**
00666  * RSTを1フレームだけ送信します。
00667  * この関数は、クローズドステータスのソケットにしてからコールします。
00668  * この関数は、アンロック状態でコールしてね。
00669  */
00670 static void sendRst(NyLPC_TcMiMicIpTcpSocket_t* i_inst)
00671 {
00672     void* buf;
00673 
00674     NyLPC_Assert(i_inst->tcpstateflags==UIP_CLOSED);
00675     //ペイロードライタの初期化
00676 
00677     //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。
00678     buf=NyLPC_cMiMicIpNetIf_allocSysTxBuf();
00679     lockResource(i_inst);
00680     i_inst->uip_connr.snd_nxt32++;
00681     unlockResource(i_inst);
00682     setTxPacket(i_inst,buf,TCP_RST|TCP_ACK,NULL,0);
00683     NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf);
00684     NyLPC_cMiMicIpNetIf_releaseTxBuf(buf);
00685     NyLPC_cIPv4Payload_finalize(&ipv4);
00686     return;
00687 }
00688 
00689 
00690 
00691 /**
00692  * 受信データをバッファに書き込む。
00693  * 十分な空き領域がない場合、失敗する。
00694  * この関数は、ロックして実行してください。
00695  */
00696 static NyLPC_TBool addRecvData(NyLPC_TcMiMicIpTcpSocket_t* i_inst,const void* i_data,NyLPC_TUInt16 i_data_size)
00697 {
00698     //受信データサイズを確認
00699     if(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf))>=i_data_size){
00700         //バッファに格納可能なら、格納。
00701         NyLPC_cFifoBuffer_push(&(i_inst->rxbuf),i_data,i_data_size);
00702     }else{
00703         //エラー:ドロップする。
00704         return NyLPC_TBool_FALSE;
00705     }
00706 
00707     return NyLPC_TBool_TRUE;
00708 }
00709 
00710 
00711 
00712 
00713 
00714 /**
00715  * Public function
00716  */
00717 static void finalize(NyLPC_TiTcpSocket_t* i_inst)
00718 {
00719     int i;
00720     NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
00721     NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService());
00722     //開放漏れの保険
00723     if(inst->txbuf.rp!=inst->txbuf.wp){
00724         lockResource(inst);
00725         resetTxQWithUnlock(inst);
00726     }
00727     for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
00728         inst->txbuf.txq[i].packet=NULL;
00729     }
00730     NyLPC_cFifoBuffer_finalize(&(inst->rxbuf));
00731 //  NyLPC_cMutex_finalize(&(i_inst->_smutex));
00732     NyLPC_cMiMicIpNetIf_releaseTcpSocketMemory(inst);
00733 
00734     return;
00735 }
00736 
00737 static NyLPC_TBool connect(NyLPC_TiTcpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_peer_port,NyLPC_TUInt32 i_wait_in_msec)
00738 {
00739     volatile NyLPC_TUInt8 f;
00740     NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
00741     NyLPC_TUInt32 sq;
00742     NyLPC_TcStopwatch_t sw;
00743     NyLPC_TUInt16 lport;
00744     lockResource(inst);
00745     //ソケットが無効であること。
00746     if(inst->tcpstateflags!=UIP_CLOSED)
00747     {
00748         NyLPC_OnErrorGoto(Error);
00749     }
00750     //ポート番号の取得(lockResourceが他のソケットと共有なので、重複ポートの割当は起こりえない。でもちょっと注意して)
00751     lport=NyLPC_htons(NyLPC_cIPv4_getNewPortNumber(inst->_parent_ipv4));
00752     if(lport==0){
00753         NyLPC_OnErrorGoto(Error);
00754     }
00755     //connectの為の準備
00756 
00757     //localipとdefault_mmsは別枠で設定
00758     /* Fill in the necessary fields for the new connection. */
00759     inst->uip_connr.current_rto32 = UIP_TCP_RTO_CONNECTION_INITIAL;//RTOを短くしてARP発行時の再接続短縮を期待する。
00760     inst->uip_connr.lport = lport;
00761     inst->uip_connr.rport = NyLPC_htons(i_peer_port);
00762     inst->uip_connr.ripaddr=*i_addr;
00763     inst->uip_connr.snd_nxt32=iss32;//should be random
00764     /* rcv_nxt should be the seqno from the incoming packet + 1. */
00765     inst->uip_connr.rcv_nxt32=0;
00766     //MSSの設定
00767     inst->uip_connr.peer_mss=inst->uip_connr.default_mss;
00768     inst->uip_connr.peer_win=1;//periodicの再送信を期待するために相手のWindowサイズは1と仮定する。
00769     NyLPC_cFifoBuffer_clear(&(inst->rxbuf));
00770     //ここでステータスがかわる。
00771     inst->tcpstateflags = UIP_SYN_SENT;
00772     //前回のデータが残っていた場合の保険
00773     if(inst->txbuf.rp!=inst->txbuf.wp){
00774         resetTxQWithUnlock(inst);
00775     }else{
00776         unlockResource(inst);
00777     }
00778 
00779     NyLPC_cStopwatch_initialize(&sw);
00780 
00781     NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
00782     if(sendWithRetransmit(inst,TCP_SYN,NULL,0,&sw,&sq)==0){
00783         //ちょっと待つ。
00784         NyLPC_cThread_yield();
00785         //キューにあるTXが消えるのを待つ。
00786         if(waitForTxRemove(inst,sq,&sw)){
00787             //ACK受信に成功して、TXが消失
00788             NyLPC_cStopwatch_finalize(&sw);
00789             return NyLPC_TBool_TRUE;
00790         }
00791     }
00792     //ロックして、強制的なステータス遷移
00793     lockResource(inst);
00794     f=inst->tcpstateflags;
00795     if(f!=UIP_CLOSED){
00796         //もし、強制CLOSE遷移であれば、RSTも送信。
00797         inst->tcpstateflags=UIP_CLOSED;
00798         unlockResource(inst);
00799         sendRst(inst);
00800     }else{
00801         unlockResource(inst);
00802     }
00803     return NyLPC_TBool_FALSE;
00804 Error:
00805     unlockResource(inst);
00806     return NyLPC_TBool_FALSE;
00807 }
00808 
00809 /**
00810  * この関数は、UIP_SYN_RCVDステータスのソケットを、ESTABLISHEDへ遷移させます。
00811  * cTcpListener_listen関数を通過したインスタンスに実行してください。
00812  * この関数は、アプリケーションが呼び出します。
00813  * @return
00814  *
00815  */
00816 static NyLPC_TBool accept(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
00817 {
00818     volatile NyLPC_TUInt8 f;
00819     NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
00820     NyLPC_TUInt32 sq;
00821     NyLPC_TcStopwatch_t sw;
00822 
00823     NyLPC_cStopwatch_initialize(&sw);
00824     //ステータスチェック
00825     f=inst->tcpstateflags;
00826     switch(f)
00827     {
00828     case UIP_ESTABLISHED:
00829         return NyLPC_TBool_TRUE;
00830     case UIP_SYN_RCVD:
00831         //処理対象
00832         break;
00833     default:
00834         return NyLPC_TBool_FALSE;
00835     }
00836     NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
00837     if(sendWithRetransmit(inst,TCP_SYN|TCP_ACK,NULL,0,&sw,&sq)==0){
00838         //ちょっと待つ。
00839         NyLPC_cThread_yield();
00840         //キューにあるTXが消えるのを待つ。
00841         if(waitForTxRemove(inst,sq,&sw)){
00842             //ACK受信に成功して、TXが消失
00843             NyLPC_cStopwatch_finalize(&sw);
00844             return NyLPC_TBool_TRUE;
00845         }
00846     }
00847     //ロックして、強制的なステータス遷移
00848     lockResource(inst);
00849     f=inst->tcpstateflags;
00850     if(f!=UIP_CLOSED){
00851         //もし、強制CLOSE遷移であれば、RSTも送信。
00852         inst->tcpstateflags=UIP_CLOSED;
00853         unlockResource(inst);
00854         sendRst(inst);
00855     }else{
00856         unlockResource(inst);
00857     }
00858     return NyLPC_TBool_FALSE;
00859 }
00860 
00861 
00862 /**
00863  * この関数は、ソケットの受信バッファの読み取り位置と、読み出せるデータサイズを返却します。
00864  * 関数はポインターを返却するだけで、バッファの読み取り位置をシークしません。
00865  * シークするにはNyLPC_cTcpSocket_pseekを使います。
00866  */
00867 static NyLPC_TInt32 precv(NyLPC_TiTcpSocket_t* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec)
00868 {
00869     NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
00870     volatile NyLPC_TUInt8 st;
00871     NyLPC_TUInt16 rlen;
00872     //タイマを生成
00873     NyLPC_TcStopwatch_t sw;
00874     NyLPC_cStopwatch_initialize(&sw);
00875 
00876     //ESTABLISHED以外の場合は、エラー。
00877     NyLPC_cStopwatch_setNow(&sw);
00878     do{
00879         //読み出しバッファ情報のコピー
00880         //MUTEX LOCK
00881         lockResource(inst);
00882         st=inst->tcpstateflags;
00883         rlen=NyLPC_cFifoBuffer_getLength(&(inst->rxbuf));
00884         *o_buf_ptr=NyLPC_cFifoBuffer_getPtr(&(inst->rxbuf));
00885         //MUTEX UNLOCK
00886         unlockResource(inst);
00887 
00888         //バッファが空の場合は、ステータスチェック。ESTABLISHEDでなければ、エラー(PASVCLOSE等の場合)
00889         switch(st){
00890         case UIP_ESTABLISHED:
00891             if(rlen>0){
00892                 //バッファにパケットがあれば返却
00893                 NyLPC_cStopwatch_finalize(&sw);
00894                 return rlen;
00895             }
00896             break;
00897         case UIP_CLOSE_WAIT:
00898             if(rlen>0){
00899                 //バッファにパケットがあれば返却
00900                 NyLPC_cStopwatch_finalize(&sw);
00901                 return rlen;
00902             }
00903             //引き続きエラー処理
00904         default:
00905             //他の場合はエラー
00906             NyLPC_cStopwatch_finalize(&sw);
00907             return -1;
00908         }
00909         //タスクスイッチ
00910         NyLPC_cThread_yield();
00911     }while(NyLPC_cStopwatch_elapseInMsec(&sw)<i_wait_msec);
00912     //規定時間内に受信が成功しなかった。
00913     NyLPC_cStopwatch_finalize(&sw);
00914     return 0;
00915 }
00916 /**
00917  * 受信バッファをシークします。
00918  * シーク後に、遅延ACKを送出します。
00919  */
00920 static void pseek(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt16 i_seek)
00921 {
00922     void* buf;
00923     NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
00924 
00925     NyLPC_ArgAssert(i_seek<=NyLPC_cFifoBuffer_getLength(&(inst->rxbuf)));
00926     if(i_seek==0){
00927         return;
00928     }
00929 
00930     //ACK送信バッファの取得
00931     buf=NyLPC_cMiMicIpNetIf_allocSysTxBuf();
00932 
00933     //MUTEX LOCK
00934     lockResource(inst);
00935 
00936     //受信バッファを読み出しシーク
00937     NyLPC_cFifoBuffer_pop(&(inst->rxbuf),i_seek);
00938     //ACKパケットの生成
00939     setTxPacket(inst,buf,TCP_ACK,NULL,0);
00940     unlockResource(inst);
00941     //ACK送信
00942     NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf);
00943     NyLPC_cMiMicIpNetIf_releaseTxBuf(buf);
00944 
00945 }
00946 
00947 /**
00948  * See header file.
00949  */
00950 static void* allocSendBuf(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_buf_size,NyLPC_TUInt32 i_wait_in_msec)
00951 {
00952     NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
00953 
00954     NyLPC_TUInt16 s;
00955     void* buf;
00956     NyLPC_TcStopwatch_t sw;
00957 
00958     NyLPC_cStopwatch_initialize(&sw);
00959     NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
00960 
00961     //送信バッファを取得
00962     //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。
00963     for(;;){
00964         //ESTABLISHED以外に非同期遷移
00965         if(inst->tcpstateflags!=UIP_ESTABLISHED){
00966             NyLPC_cStopwatch_finalize(&sw);
00967             return NULL;
00968         }
00969         buf=NyLPC_cMiMicIpNetIf_allocTxBuf(i_hint+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
00970         if(buf!=NULL){
00971             break;
00972         }
00973         //タイムアウト時もエラー
00974         if(NyLPC_cStopwatch_isExpired(&sw)){
00975             NyLPC_cStopwatch_finalize(&sw);
00976             return NULL;
00977         }
00978     }
00979 
00980 //@todo 前段処理と順番を入れ替えて、要求サイズとpeerのwinのうち、小さいほうを割り当てたほうが良くない?
00981 //ここで相手のwin待ちをする理由は、相手に確実に受け取れるサイズを決定する為。
00982     lockResource(inst);
00983     //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
00984     while(inst->uip_connr.peer_win==0){
00985         unlockResource(inst);
00986         //ESTABLISHED以外に非同期遷移 orタイムアウト確認
00987         if(NyLPC_cStopwatch_isExpired(&sw)||(inst->tcpstateflags!=UIP_ESTABLISHED)){
00988             NyLPC_cMiMicIpNetIf_releaseTxBuf(buf);
00989             NyLPC_cStopwatch_finalize(&sw);
00990             return NULL;
00991         }
00992         NyLPC_cThread_yield();
00993         lockResource(inst);
00994     }
00995     //送信バッファを基準とした送信サイズを計算
00996     s-=SIZE_OF_IPv4_TCPIP_HEADER;
00997     //送信サイズよりMMSが小さければ、送信サイズを修正
00998     if(inst->uip_connr.peer_mss<s){
00999         s=inst->uip_connr.peer_mss;
01000     }
01001     //送信サイズよりpeerのウインドウサイズが小さければ修正
01002     if(inst->uip_connr.peer_win<s){
01003         s=inst->uip_connr.peer_win;
01004     }
01005     unlockResource(inst);
01006     //バッファサイズ確定。
01007     *o_buf_size=s;
01008     NyLPC_cStopwatch_finalize(&sw);
01009     return (NyLPC_TUInt8*)buf+SIZE_OF_IPv4_TCPIP_HEADER;
01010 }
01011 /**
01012  * See Header file.
01013  */
01014 static void releaseSendBuf(NyLPC_TiTcpSocket_t* i_inst,void* i_buf_ptr)
01015 {
01016     NyLPC_cMiMicIpNetIf_releaseTxBuf((NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER);
01017 }
01018 
01019 
01020 /**
01021  * 事前にAllocしたTxパケットを送信します。
01022  * このAPIはゼロコピー送信をサポートするためのものです。
01023  * @param i_buf_ptr
01024  * allocSendBufで取得したメモリを指定します。
01025  * @return
01026  * 関数が失敗した場合、i_buf_ptrは「開放されません。」
01027  */
01028 static NyLPC_TBool psend(NyLPC_TiTcpSocket_t* i_inst,void* i_buf_ptr,int i_len,NyLPC_TUInt32 i_wait_in_msec)
01029 {
01030     NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
01031     struct NyLPC_TcTcpSocket_TxQItem* txq;
01032     void* buf;
01033     NyLPC_TcStopwatch_t sw;
01034     //ESTABLISHEDでなければエラー
01035     if(inst->tcpstateflags!=UIP_ESTABLISHED){
01036         //ESTABLISHEDでなければエラー
01037         return NyLPC_TBool_FALSE;
01038     }
01039     //送信データ0なら何もしない。
01040     if(i_len<1){
01041         releaseSendBuf(i_inst,i_buf_ptr);
01042         return NyLPC_TBool_TRUE;
01043     }
01044     NyLPC_cStopwatch_initialize(&sw);
01045     NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
01046 
01047     //先頭ポインタは、i_buf-sizeof(SIZE_OF_IPv4_TCPIP_HEADER)固定
01048     buf=(NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER;
01049     lockResource(inst);
01050     //送信キューの取得
01051     txq=getTxQ(inst,&sw);
01052     //送信キューが取れなかった。
01053     if(txq==NULL){
01054         //シーケンス番号をロールバックできないので、エラーとする。
01055         unlockResource(inst);
01056         NyLPC_cStopwatch_finalize(&sw);
01057         return NyLPC_TBool_FALSE;
01058     }
01059     //ここから先はi_bufの所有権はインスタンスになってる。
01060 
01061     //IPv4ペイロードの書き込み
01062 
01063     //allocをした時点でwin,mssは考慮されているので、そのままそうしんしる。
01064 
01065     //ACK番号の計算
01066     txq->rto32=inst->uip_connr.current_rto32;
01067     txq->tick_of_sent=NyLPC_cStopwatch_now();
01068     //パケットヘッダの生成(ヘッダ長はpreadで定義した値(4+6)*4=40です。)
01069     setTxPacketHeader(inst,buf,TCP_ACK|TCP_PSH,i_len);
01070     txq->packet=buf;
01071 
01072     //シーケンス番号の更新
01073     inst->uip_connr.snd_nxt32=inst->uip_connr.snd_nxt32+i_len;
01074     //Peerのウインドウサイズを更新
01075     inst->uip_connr.peer_win-=i_len;
01076     //ACK番号の返却
01077     txq->ackno=NyLPC_HTONL(inst->uip_connr.snd_nxt32);
01078     unlockResource(inst);
01079     NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf);
01080     NyLPC_cStopwatch_finalize(&sw);
01081     return NyLPC_TBool_TRUE;
01082 }
01083 
01084 /**
01085  * See header file.
01086  */
01087 static NyLPC_TInt32 send(NyLPC_TiTcpSocket_t* i_inst,const void* i_buf_ptr,NyLPC_TInt32 i_len,NyLPC_TUInt32 i_wait_in_msec)
01088 {
01089     NyLPC_TInt16 hint;
01090     NyLPC_TUInt16 s;
01091     void* buf;
01092     if(i_len<1){
01093         return 0;
01094     }
01095     hint=(i_len>32767)?32767:i_len;
01096     buf=allocSendBuf(i_inst,hint,&s,i_wait_in_msec);
01097     if(buf==NULL){
01098         return -1;
01099     }
01100     //送信サイズの計算
01101     s=((NyLPC_TInt32)s<i_len)?s:(NyLPC_TUInt16)i_len;
01102     memcpy(buf,i_buf_ptr,s);
01103     if(!psend(i_inst,buf,s,i_wait_in_msec)){
01104         releaseSendBuf(i_inst,buf);
01105         return -1;//error
01106     }
01107     return s;
01108 }
01109 
01110 
01111 static void close(NyLPC_TiTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
01112 {
01113     NyLPC_TcMiMicIpTcpSocket_t* inst=(NyLPC_TcMiMicIpTcpSocket_t*)i_inst;
01114     NyLPC_TcStopwatch_t sw;
01115     volatile NyLPC_TUInt8 f;
01116     NyLPC_TUInt32 sq;
01117     NyLPC_cStopwatch_initialize(&sw);
01118     NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
01119     lockResource(inst);
01120 
01121     f=inst->tcpstateflags;
01122     //ステータスチェック
01123     switch(f)
01124     {
01125     case UIP_CLOSED:
01126         //閉じている。
01127         goto ReturnWithUnlock;
01128     case UIP_ESTABLISHED:
01129         //アクティブクローズ。
01130         inst->tcpstateflags=UIP_FIN_WAIT_1;
01131         //送信のために一旦解除
01132         unlockResource(inst);
01133         //FINの送信
01134         if(sendWithRetransmit(inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
01135             //ちょっと待つ。
01136             NyLPC_cThread_yield();
01137             //TXの消去待ち
01138             if(waitForTxRemove(inst,sq,&sw)){
01139                 //再ロック
01140                 lockResource(inst);
01141                 //タイムアウトするか、UIP_CLOSED、もしくはTIME_WAITに遷移するのを待つ。(遷移はRxprocで自動的に実行。)
01142                 do{
01143                     switch(inst->tcpstateflags)
01144                     {
01145                     case UIP_TIME_WAIT:
01146                         inst->tcpstateflags=UIP_CLOSED;
01147                     case UIP_CLOSED:
01148                         NyLPC_Assert(inst->txbuf.rp==inst->txbuf.wp);
01149                         //成功。
01150                         goto ReturnWithUnlock;
01151                     case UIP_FIN_WAIT_1:
01152                     case UIP_FIN_WAIT_2:
01153                     case UIP_CLOSING:
01154                         //一時的なアンロック
01155                         unlockResource(inst);
01156                         NyLPC_cThread_yield();
01157                         lockResource(inst);
01158                     default:
01159                         break;
01160                     }
01161                 }while(!NyLPC_cStopwatch_isExpired(&sw));
01162                 unlockResource(inst);
01163             }
01164         }
01165         break;
01166     case UIP_CLOSE_WAIT:
01167         //LAST_ACKへ遷移
01168         inst->tcpstateflags=UIP_LAST_ACK;
01169         //送信のために一旦解除
01170         unlockResource(inst);
01171         if(sendWithRetransmit(inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
01172             //ちょっと待つ。
01173             NyLPC_cThread_yield();
01174             //TXの消去待ち
01175             if(waitForTxRemove(inst,sq,&sw)){
01176                 //再ロック
01177                 lockResource(inst);
01178                 //TX消去後にCLOSEDに遷移していればOK
01179                 if(inst->tcpstateflags==UIP_CLOSED)
01180                 {
01181                     NyLPC_Assert(inst->txbuf.rp==inst->txbuf.wp);
01182                     goto ReturnWithUnlock;
01183                 }
01184                 unlockResource(inst);
01185             }
01186         }
01187         //エラー。RSTで切断。
01188         break;
01189     default:
01190         unlockResource(inst);
01191         NyLPC_Warning();
01192         break;
01193     }
01194 //  if(i_inst->_smutex._lock_count>0){
01195 //      NyLPC_Warning();
01196 //  }
01197     //このパスに到達するのは、FIN送信/ACKに成功したにも拘らず、規定時間内にCLOSEDに遷移しなかった場合。
01198     //コネクションを強制遷移して、RST
01199     lockResource(inst);
01200     f=inst->tcpstateflags;
01201     if(f!=UIP_CLOSED){
01202         //もし、強制CLOSE遷移であれば、RSTも送信。
01203         inst->tcpstateflags=UIP_CLOSED;
01204         unlockResource(inst);
01205         sendRst(inst);
01206     }else{
01207         unlockResource(inst);
01208     }
01209     NyLPC_cStopwatch_finalize(&sw);
01210     return;
01211 ReturnWithUnlock:
01212     unlockResource(inst);
01213     NyLPC_cStopwatch_finalize(&sw);
01214     return;
01215 }
01216 
01217 /**
01218  * uipサービスタスクが実行する関数です。
01219  * 定期的に実行する関数。最低でも1s単位で実行してください。
01220  */
01221 void NyLPC_cMiMicIpTcpSocket_periodic(
01222     NyLPC_TcMiMicIpTcpSocket_t* i_inst)
01223 {
01224     int i;
01225     struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
01226     NyLPC_TcStopwatch_t sw;
01227     NyLPC_TUInt32 now;
01228     int rp;
01229     NyLPC_cStopwatch_initialize(&sw);
01230     now=NyLPC_cStopwatch_now();
01231     //MUTEX LOCK
01232     lockResource(i_inst);
01233     if(i_inst->tcpstateflags==UIP_CLOSED)
01234     {
01235         //CLOSEDなら、バッファ開放。
01236         resetTxQWithUnlock(i_inst);
01237     }else if(i_inst->txbuf.rp==i_inst->txbuf.wp){
01238         //再送信パケットがなければ何もしないよ。
01239         unlockResource(i_inst);
01240     }else if(i_inst->uip_connr.peer_win==0){
01241         //peer_winが0の場合は何もしない。
01242         unlockResource(i_inst);
01243     }else{
01244         //再送信処理
01245         rp=i_inst->txbuf.rp;
01246         NyLPC_cStopwatch_set(&sw,q[rp].tick_of_sent);
01247         if(NyLPC_cStopwatch_elapseInMsec(&sw)>q[rp].rto32){
01248             //最古のパケットの送信時間をチェックして、タイムアウトが発生したら、再送時間と送信時刻をセット
01249             //最古パケットRTOを2倍。
01250             q[rp].rto32*=2;
01251             for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
01252                 q[i].tick_of_sent=now;
01253             }
01254             if(q[rp].rto32>UIP_IP_RTO_MAX_RTO){
01255                 //最古のRTOが64秒を超えたら、CLOSED
01256                 i_inst->tcpstateflags =UIP_CLOSED;
01257                 resetTxQWithUnlock(i_inst);
01258                 sendRst(i_inst);
01259             }else{
01260                 //規定時間内なら、再送処理
01261                 for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
01262 //                  NyLPC_cUipService_sendIPv4Tx(NyLPC_cIPv4Payload_getBuf(&(q[i].data)));
01263                     NyLPC_cMiMicIpNetIf_sendIPv4Tx(q[i].packet);
01264                 }
01265                 unlockResource(i_inst);
01266             }
01267         }else{
01268             unlockResource(i_inst);
01269         }
01270     }
01271     NyLPC_cStopwatch_finalize(&sw);
01272     return;
01273 }
01274 /**
01275  * uipサービスタスクが実行する関数です。
01276  * サービスの開始を通知します。
01277  */
01278 void NyLPC_cMiMicIpTcpSocket_startService(NyLPC_TcMiMicIpTcpSocket_t* i_inst,const NyLPC_TcIPv4Config_t* i_config)
01279 {
01280     NyLPC_Assert(i_inst->tcpstateflags==UIP_CLOSED);//閉じてなければおかしい。
01281     i_inst->uip_connr.lipaddr=&(i_config->ip_addr);
01282     i_inst->uip_connr.default_mss=i_config->default_mss;
01283     //NyLPC_cTcpSocket_setSynPayload関数でも実行するけど、IFのリセット時なのでここでもやる。
01284     NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
01285     return;
01286 }
01287 /**
01288  * uipサービスタスクが実行する関数です。
01289  * サービスの停止を通知します。
01290  */
01291 void NyLPC_cMiMicIpTcpSocket_stopService(NyLPC_TcMiMicIpTcpSocket_t* i_inst)
01292 {
01293     lockResource(i_inst);
01294     if(i_inst->tcpstateflags==UIP_CLOSED)
01295     {
01296         unlockResource(i_inst);
01297     }else{
01298         i_inst->tcpstateflags=UIP_CLOSED;
01299         resetTxQWithUnlock(i_inst);
01300         sendRst(i_inst);
01301     }
01302     return;
01303 }
01304 
01305 
01306 void* NyLPC_cMiMicIpTcpSocket_parseRx(
01307     NyLPC_TcMiMicIpTcpSocket_t* i_inst,
01308     const NyLPC_TcIPv4Payload_t* i_ipp)
01309 {
01310     int i,s;
01311     NyLPC_TUInt16 tmp16;
01312     NyLPC_TUInt16 data_size;
01313     NyLPC_TUInt8 in_tcpflag=i_ipp->payload.tcp->flags;
01314     const void* tcp_data_offset;
01315     NyLPC_TBool is_new_packet;
01316     int num_of_noack;
01317     void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
01318     void* ret;
01319 
01320     //パラメータの計算
01321 
01322     tmp16=NyLPC_TTcpHeader_getHeaderLength(i_ipp->payload.tcp);
01323     //TCPペイロードの長さは、IPパケットの長さ-(IPヘッダ+TCPヘッダ)
01324     data_size=NyLPC_TIPv4Header_getPacketLength(i_ipp->header)-NyLPC_TIPv4Header_getHeaderLength(i_ipp->header)-tmp16;
01325     //TCPデータオフセット
01326     tcp_data_offset=i_ipp->payload.rawbuf+tmp16;
01327 
01328     //インスタンスをロックする。
01329     lockResource(i_inst);
01330 
01331     //RSTのチェック。RST受信時は、状態にかかわらず、CLOSEDステータスに移行する。
01332     if (in_tcpflag & TCP_RST)
01333     {
01334         i_inst->tcpstateflags =UIP_CLOSED;
01335         goto DROP;
01336     }
01337 
01338 
01339     is_new_packet=NyLPC_ntohl(i_ipp->payload.tcp->seqno32)==i_inst->uip_connr.rcv_nxt32;
01340 
01341 
01342     //OPTIONの反映
01343 
01344     //MSSの取得
01345     if(NyLPC_TTcpHeader_getTcpMmsOpt(i_ipp->payload.tcp,&tmp16)){
01346         //取得で着たら更新
01347         i_inst->uip_connr.peer_mss=tmp16;
01348     }
01349     //受信パケットを元に、未ACKパケットの数を計算
01350     num_of_noack=getNumOfSending(i_inst,i_ipp->payload.tcp->ackno32);//i_inst->txbuf.num_of_txq;
01351 
01352     //ステータス毎のACK応答
01353     switch(i_inst->tcpstateflags)
01354     {
01355     case UIP_SYN_RCVD:
01356         //ACKを受信したら、ESTABLISHEDへ。
01357         //すべてのパケットをACKしたかで判定。()
01358         if(num_of_noack==0){
01359             i_inst->tcpstateflags=UIP_ESTABLISHED;
01360         }else{
01361             //それ以外のパケットはドロップする。
01362             break;//goto DROP;
01363         }
01364         //新しいパケットがなければ、無応答
01365         if(!is_new_packet){
01366             break;//goto DROP;
01367         }
01368         //引き続き、ESTABLISHEDの処理へ。
01369     case UIP_ESTABLISHED:
01370         if(data_size>0){
01371             if(is_new_packet){
01372                 if(addRecvData(i_inst,tcp_data_offset,data_size)){
01373                     //通常のACK返却
01374                     i_inst->uip_connr.rcv_nxt32+=data_size;
01375                 }else{
01376                     //失敗したときは必要に応じて単純ACK
01377                 }
01378             }
01379         }
01380         //どちらにしろ、ACK送信
01381         if(is_new_packet && (in_tcpflag & TCP_FIN)){
01382             //FINがあるときは、ステータスをCLOSE_WAITへセットして、ACKを返す。
01383             i_inst->tcpstateflags = UIP_CLOSE_WAIT;
01384             i_inst->uip_connr.rcv_nxt32++;
01385         }
01386         break;
01387     case UIP_CLOSE_WAIT:
01388         //必要に応じたACK応答
01389         break;
01390     case UIP_LAST_ACK:
01391         //ACK(by FIN)が得られたなら、CLOSEDへ。
01392         if(num_of_noack==0){
01393             i_inst->tcpstateflags=UIP_CLOSED;
01394         }
01395         //必要に応じたACK応答
01396         break;
01397     case UIP_FIN_WAIT_1:
01398         //FIN受信->CLOSINGへ
01399         if(is_new_packet){
01400             i_inst->uip_connr.rcv_nxt32+=data_size;
01401             if(in_tcpflag & TCP_FIN){
01402                 i_inst->uip_connr.rcv_nxt32++;
01403                 if(num_of_noack==0){
01404                     //FINとACKを受信
01405                     i_inst->tcpstateflags=UIP_TIME_WAIT;
01406                 }else{
01407                     //FINのみ
01408                     i_inst->tcpstateflags=UIP_CLOSING;
01409                 }
01410             }
01411         }else if(num_of_noack==0){
01412             //ACKのみ
01413             i_inst->tcpstateflags=UIP_FIN_WAIT_2;
01414         }
01415         //必要に応じたACK応答
01416         break;
01417     case UIP_FIN_WAIT_2:
01418         //FIN受信->TIME_WAITへ(pureACK)
01419         if(is_new_packet && (in_tcpflag & TCP_FIN)){
01420             i_inst->uip_connr.rcv_nxt32++;
01421             i_inst->tcpstateflags=UIP_TIME_WAIT;
01422         }
01423         break;
01424     case UIP_CLOSING:
01425         //ACK受信したら、TIME_WAITへ
01426         if(num_of_noack==0){
01427             i_inst->tcpstateflags=UIP_TIME_WAIT;
01428         }
01429         break;
01430     case UIP_CLOSED:
01431         //何もできない。何もしない。
01432         break;
01433     case UIP_TIME_WAIT:
01434         //最終ACKを送り続ける。
01435         break;
01436     case UIP_SYN_SENT:
01437         //connect関数実行中しか起動しないステータス
01438         if(num_of_noack==0){
01439             i_inst->tcpstateflags=UIP_ESTABLISHED;
01440             i_inst->uip_connr.rcv_nxt32=NyLPC_ntohl(i_ipp->payload.tcp->seqno32)+1;
01441         }else{
01442             //それ以外のパケットはドロップする。
01443             break;//goto DROP;
01444         }
01445         //ACKを送る。
01446         break;
01447     default:
01448         goto DROP;
01449     }
01450     //ウインドウサイズを更新
01451     i_inst->uip_connr.peer_win=NyLPC_ntohs(i_ipp->payload.tcp->wnd16);
01452 
01453     //送信キューから、Peerが受信したデータを削除する。
01454     if(in_tcpflag & TCP_ACK){
01455         //再送パケットキューから送信済みのデータを回収(後で開放)
01456         NyLPC_Trace();
01457         s=updateTxQByIndex(i_inst,i_ipp->payload.tcp->ackno32,dlist);
01458         NyLPC_Trace();
01459     }else{
01460         s=0;
01461     }
01462     //新しいパケットがきた場合は、再送キューのACKを更新する。
01463     if(is_new_packet){
01464         //再送キューのACKを更新
01465         updateTxAck(i_inst,NyLPC_htonl(i_inst->uip_connr.rcv_nxt32));
01466     }
01467 
01468     //送信キューのない
01469     if(((in_tcpflag&(TCP_FIN|TCP_SYN))!=0x00) ||
01470         ((!is_new_packet) && (data_size>0)))
01471     {
01472         //ソケットからPureACKを生成 as setPacket(i_inst,i_ipp,TCP_ACK,NULL,0);
01473         ret=NyLPC_cMiMicIpNetIf_allocSysTxBuf();
01474         setTxPacket(i_inst,ret,TCP_ACK,NULL,0);
01475     }else{
01476         ret=NULL;
01477     }
01478     unlockResource(i_inst);
01479     //取り外したTXメモリの開放
01480     for(i=0;i<s;i++){
01481         //取り外したTXメモリを開放
01482         NyLPC_cMiMicIpNetIf_releaseTxBuf(dlist[i]);
01483     }
01484 NyLPC_Trace();
01485     return ret;
01486 DROP:
01487     //ACKしたパケットを送信キューから削除
01488     unlockResource(i_inst);
01489 NyLPC_Trace();
01490     return NULL;
01491 }
01492 
01493 
01494 /**
01495  * 入力されたパケットからRSTパケットを生成して返す。
01496  */
01497 void* NyLPC_cMiMicIpTcpSocket_allocTcpReverseRstAck(
01498     const NyLPC_TcIPv4Payload_t* i_src)
01499 {
01500     struct NyLPC_TIPv4Header*   iph;
01501     struct NyLPC_TTcpHeader*    tcph;
01502     NyLPC_TUInt8 iph_word=0x05;
01503     NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
01504     void* txb=NyLPC_cMiMicIpNetIf_allocSysTxBuf();
01505     //IPヘッダの更新
01506     iph=(struct NyLPC_TIPv4Header*)txb;
01507     iph->vhl=0x40|(0x0f&iph_word);
01508     iph->destipaddr=i_src->header->srcipaddr;
01509     iph->srcipaddr =i_src->header->destipaddr;
01510     NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
01511 
01512     //TCPヘッダの更新
01513     tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)txb)+NyLPC_TIPv4Header_getHeaderLength(iph));
01514 
01515     tcph->tcpoffset=(tcph_word<<4);
01516 
01517     tcph->flags    = TCP_RST | TCP_ACK;
01518     //sorce & destination port
01519     tcph->srcport  = i_src->payload.tcp->destport;
01520     tcph->destport = i_src->payload.tcp->srcport;
01521     //ACK number
01522     tcph->ackno32  = NyLPC_htonl(NyLPC_ntohl(i_src->payload.tcp->seqno32)+1);
01523     //Seq Number
01524     tcph->seqno32  = i_src->payload.tcp->ackno32;
01525     //uip_func_tcp_send_noconn(BUF);
01526     tcph->urgp[0]  = tcph->urgp[1] = 0;
01527     tcph->tcpchksum= 0;
01528 
01529 
01530     //最終的なパケットサイズと必要ならペイロードを書き込み
01531     iph->len16=NyLPC_htons((iph_word+tcph_word)*4);
01532     //WND設定
01533     tcph->wnd16=0;
01534     //Checksumの生成
01535     tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
01536     iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
01537     return txb;
01538 }
01539 
01540 
01541 
01542