Ryo Iizuka / libMiMic

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

Revision:
57:bc4330dfa62f
Parent:
43:a182f2b5ff41
Child:
58:03b89038b21a
--- a/core/uip/NyLPC_cTcpSocket.c	Sat Aug 10 02:52:22 2013 +0000
+++ b/core/uip/NyLPC_cTcpSocket.c	Fri Sep 13 06:38:16 2013 +0000
@@ -31,6 +31,29 @@
 static NyLPC_TUInt32 iss32=3939;
 #define SIZE_OF_IPv4_TCPIP_HEADER 40
 
+/**
+ * TCPのRTOの最大値。
+ * ms単位である。
+ * defaultは64SEC
+ */
+#define UIP_IP_RTO_MAX_RTO 64000
+/**
+ * TCPのRTOの初期値。
+ * ms単位である。
+ * 伝送路の特性に合わせて調整すること。
+ */
+#define UIP_TCP_RTO_INITIAL 3000
+
+/**
+ * CONNECTION時のRTO
+ */
+#define UIP_TCP_RTO_CONNECTION_INITIAL 200
+
+/**
+ * 下限値
+ */
+#define UIP_TCP_RTO_MINIMUM 100
+
 
 /**
  * for Debug
@@ -44,11 +67,10 @@
     #define DEBUG_RTO_LOG(i_inst)
 #endif
 
-
 //#define lockResource(i_inst) NyLPC_cMutex_lock(&((i_inst)->_smutex))
 //#define unlockResource(i_inst) NyLPC_cMutex_unlock(&((i_inst)->_smutex))
-#define lockResource(i_inst) NyLPC_cMutex_lock(((i_inst)->_smutex))
-#define unlockResource(i_inst) NyLPC_cMutex_unlock(((i_inst)->_smutex))
+#define lockResource(i_inst) NyLPC_cMutex_lock(NyLPC_cIPv4_getSockMutex(((i_inst)->_super._parent_ipv4)))
+#define unlockResource(i_inst) NyLPC_cMutex_unlock(NyLPC_cIPv4_getSockMutex(((i_inst)->_super._parent_ipv4)))
 
 static void sendRst(NyLPC_TcTcpSocket_t* i_inst);
 
@@ -225,8 +247,8 @@
         break;
     }
     NyLPC_cStopwatch_finalize(&sw);
-    if(new_rto<UIP_IP_RTO_MINIMUM){
-        new_rto=UIP_IP_RTO_MINIMUM;
+    if(new_rto<UIP_TCP_RTO_MINIMUM){
+        new_rto=UIP_TCP_RTO_MINIMUM;
     }
     i_inst->uip_connr.current_rto32=new_rto;
 }
@@ -312,7 +334,7 @@
 
     NyLPC_cFifoBuffer_initialize(&(i_inst->rxbuf),i_rbuf,i_rbuf_len);
     //  NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(i_inst->_smutex)));//個別Mutex
-    i_inst->_smutex=NyLPC_cIPv4_getSockMutex(&(srv->_tcpv4));//共有Mutex
+//  i_inst->_smutex=NyLPC_cIPv4_getSockMutex(&(srv->_tcpv4));//共有Mutex
     i_inst->tcpstateflags=UIP_CLOSED;
     i_inst->txbuf.rp=i_inst->txbuf.wp=0;
     for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
@@ -356,7 +378,7 @@
     {
         //localipとdefault_mmsは別枠で設定
         /* Fill in the necessary fields for the new connection. */
-        i_inst->uip_connr.current_rto32 = UIP_IP_RTOP_INITIAL;
+        i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_INITIAL;
         i_inst->uip_connr.lport = i_lport;
         i_inst->uip_connr.rport = i_lq->rport;
         i_inst->uip_connr.ripaddr=i_lq->srcaddr;
@@ -364,20 +386,17 @@
         /* rcv_nxt should be the seqno from the incoming packet + 1. */
         i_inst->uip_connr.rcv_nxt32= i_lq->rcv_nxt32;
         //MSSの設定
-        i_inst->uip_connr.peer_mss=i_inst->uip_connr.default_mss;
-        if(i_lq->mss!=0){
-            i_inst->uip_connr.peer_mss=i_lq->mss;
-        }
+        i_inst->uip_connr.peer_mss=(i_lq->mss!=0)?i_lq->mss:i_inst->uip_connr.default_mss;
         i_inst->uip_connr.peer_win=0;
         NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
+        //ここでステータスがかわる。
+        i_inst->tcpstateflags = UIP_SYN_RCVD;
         //前回のデータが残っていた場合の保険
         if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
             resetTxQWithUnlock(i_inst);
         }else{
             unlockResource(i_inst);
         }
-        //ここでステータスがかわる。
-        i_inst->tcpstateflags = UIP_SYN_RCVD;
         return NyLPC_TBool_TRUE;
     }
     unlockResource(i_inst);
@@ -496,7 +515,7 @@
         s=i_len;
     }
     //ACK番号の計算
-    next_ack=i_inst->uip_connr.snd_nxt32+s+((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00?1:0);
+    next_ack=i_inst->uip_connr.snd_nxt32+s+(((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00)?1:0);
     txq->rto32=i_inst->uip_connr.current_rto32;
     txq->tick_of_sent=NyLPC_cStopwatch_now();
 
@@ -561,6 +580,7 @@
         //エラー:ドロップする。
         return NyLPC_TBool_FALSE;
     }
+
     return NyLPC_TBool_TRUE;
 }
 
@@ -571,6 +591,77 @@
  * Public function
  */
 
+NyLPC_TBool NyLPC_cTcpSocket_connect(NyLPC_TcTcpSocket_t* i_inst,struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_peer_port,NyLPC_TUInt32 i_wait_in_msec)
+{
+    volatile NyLPC_TUInt8 f;
+    NyLPC_TUInt32 sq;
+    NyLPC_TcStopwatch_t sw;
+    NyLPC_TUInt16 lport;
+    lockResource(i_inst);
+    //ソケットが無効であること。
+    if(i_inst->tcpstateflags!=UIP_CLOSED)
+    {
+        NyLPC_OnErrorGoto(Error);
+    }
+    //ポート番号の取得(lockResourceが他のソケットと共有なので、重複ポートの割当は起こりえない。でもちょっと注意して)
+    lport=NyLPC_htons(NyLPC_cIPv4_getNewPortNumber(i_inst->_super._parent_ipv4));
+    if(lport==0){
+        NyLPC_OnErrorGoto(Error);
+    }
+    //connectの為の準備
+
+    //localipとdefault_mmsは別枠で設定
+    /* Fill in the necessary fields for the new connection. */
+    i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_CONNECTION_INITIAL;//RTOを短くしてARP発行時の再接続短縮を期待する。
+    i_inst->uip_connr.lport = lport;
+    i_inst->uip_connr.rport = NyLPC_htons(i_peer_port);
+    i_inst->uip_connr.ripaddr=*i_addr;
+    i_inst->uip_connr.snd_nxt32=iss32;//should be random
+    /* rcv_nxt should be the seqno from the incoming packet + 1. */
+    i_inst->uip_connr.rcv_nxt32=0;
+    //MSSの設定
+    i_inst->uip_connr.peer_mss=i_inst->uip_connr.default_mss;
+    i_inst->uip_connr.peer_win=1;//periodicの再送信を期待するために相手のWindowサイズは1と仮定する。
+    NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
+    //ここでステータスがかわる。
+    i_inst->tcpstateflags = UIP_SYN_SENT;
+    //前回のデータが残っていた場合の保険
+    if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
+        resetTxQWithUnlock(i_inst);
+    }else{
+        unlockResource(i_inst);
+    }
+
+    NyLPC_cStopwatch_initialize(&sw);
+
+    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
+    if(sendWithRetransmit(i_inst,TCP_SYN,NULL,0,&sw,&sq)==0){
+        //ちょっと待つ。
+        NyLPC_cThread_yield();
+        //キューにあるTXが消えるのを待つ。
+        if(waitForTxRemove(i_inst,sq,&sw)){
+            //ACK受信に成功して、TXが消失
+            NyLPC_cStopwatch_finalize(&sw);
+            return NyLPC_TBool_TRUE;
+        }
+    }
+    //ロックして、強制的なステータス遷移
+    lockResource(i_inst);
+    f=i_inst->tcpstateflags;
+    if(f!=UIP_CLOSED){
+        //もし、強制CLOSE遷移であれば、RSTも送信。
+        i_inst->tcpstateflags=UIP_CLOSED;
+        unlockResource(i_inst);
+        sendRst(i_inst);
+    }else{
+        unlockResource(i_inst);
+    }
+    return NyLPC_TBool_FALSE;
+Error:
+    unlockResource(i_inst);
+    return NyLPC_TBool_FALSE;
+}
+
 /**
  * この関数は、UIP_SYN_RCVDステータスのソケットを、ESTABLISHEDへ遷移させます。
  * cTcpListener_listen関数を通過したインスタンスに実行してください。
@@ -612,12 +703,12 @@
     lockResource(i_inst);
     f=i_inst->tcpstateflags;
     if(f!=UIP_CLOSED){
+        //もし、強制CLOSE遷移であれば、RSTも送信。
         i_inst->tcpstateflags=UIP_CLOSED;
-    }
-    unlockResource(i_inst);
-    //もし、強制CLOSE遷移であれば、RSTも送信。
-    if(f!=UIP_CLOSED){
+        unlockResource(i_inst);
         sendRst(i_inst);
+    }else{
+        unlockResource(i_inst);
     }
     return NyLPC_TBool_FALSE;
 }
@@ -861,7 +952,7 @@
     if(i_len<1){
         return 0;
     }
-    hint=(i_len>32767)?32767:0;
+    hint=(i_len>32767)?32767:i_len;
     buf=NyLPC_cTcpSocket_allocSendBuf(i_inst,hint,&s,i_wait_in_msec);
     if(buf==NULL){
         return -1;
@@ -967,12 +1058,12 @@
     lockResource(i_inst);
     f=i_inst->tcpstateflags;
     if(f!=UIP_CLOSED){
+        //もし、強制CLOSE遷移であれば、RSTも送信。
         i_inst->tcpstateflags=UIP_CLOSED;
-    }
-    unlockResource(i_inst);
-    //もし、強制CLOSE遷移であれば、RSTも送信。
-    if(f!=UIP_CLOSED){
+        unlockResource(i_inst);
         sendRst(i_inst);
+    }else{
+        unlockResource(i_inst);
     }
     NyLPC_cStopwatch_finalize(&sw);
     return;
@@ -1149,8 +1240,8 @@
                 }
             }
         }
-        //MSSとWNDの更新
-        i_inst->uip_connr.peer_mss = i_inst->uip_connr.default_mss;
+//      //MSSとWNDの更新
+//      i_inst->uip_connr.peer_mss = i_inst->uip_connr.default_mss;//@bug じゃないのこれ。peer_mss勝手に上書きしたらダメだろ
         //どちらにしろ、ACK送信
         if(is_new_packet && (in_tcpflag & TCP_FIN)){
             //FINがあるときは、ステータスをCLOSE_WAITへセットして、ACKを返す。
@@ -1200,10 +1291,21 @@
         break;
     case UIP_CLOSED:
         //何もできない。何もしない。
-        break;//goto DROP;
+        break;
     case UIP_TIME_WAIT:
         //最終ACKを送り続ける。
         break;
+    case UIP_SYN_SENT:
+        //connect関数実行中しか起動しないステータス
+        if(num_of_noack==0){
+            i_inst->tcpstateflags=UIP_ESTABLISHED;
+            i_inst->uip_connr.rcv_nxt32=NyLPC_ntohl(o_ipp->payload.tcp->seqno32)+1;
+        }else{
+            //それ以外のパケットはドロップする。
+            break;//goto DROP;
+        }
+        //ACKを送る。
+        break;
     default:
         goto DROP;
     }