Ryo Iizuka / libMiMic

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

Revision:
37:fc4b4fd6a649
Parent:
12:efe841863fc8
Child:
43:a182f2b5ff41
diff -r f02596009a02 -r fc4b4fd6a649 core/uip/NyLPC_cIPv4.c
--- a/core/uip/NyLPC_cIPv4.c	Thu May 16 16:06:46 2013 +0000
+++ b/core/uip/NyLPC_cIPv4.c	Wed Jun 19 09:33:01 2013 +0000
@@ -53,9 +53,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "NyLPC_stdlib.h"
+#include "NyLPC_uip.h"
 #include "NyLPC_cIPv4.h"
 #include "NyLPC_cIPv4Payload_protected.h"
 #include "NyLPC_cTcpSocket_protected.h"
+#include "NyLPC_cUdpSocket_protected.h"
 #include "NyLPC_cTcpListener_protected.h"
 #include "NyLPC_cIPv4IComp_protected.h"
 #include "NyLPC_cUipService_protected.h"
@@ -63,86 +65,192 @@
 
 
 /****************************************************
- * Listenerテーブルに関する宣言
- ***************************************************/
-
-
-
-#define cListenerTbl_initialize(i_inst,buf) NyLPC_cPtrTbl_initialize(i_inst,buf,NyLPC_cIPv4_MAX_TCP_LISTENER)
-
-/**
- * i_peer番号に一致するリスナを返します。
- */
-static NyLPC_TcTcpListener_t* cListenerTbl_getByPeerPort(NyLPC_TcPtrTbl_t* i_inst,NyLPC_TUInt16 i_peer_port)
-{
-    NyLPC_TcTcpListener_t** p=(NyLPC_TcTcpListener_t**)(i_inst->buf);
-    int i;
-    //一致するポートを検索して、acceptをコールする。
-    for(i=i_inst->size-1;i>=0;i--){
-        if(p[i]==NULL){
-            continue;
-        }
-        if(p[i]->_port!=i_peer_port){
-            continue;
-        }
-        return p[i];
-    }
-    return NULL;
-}
-
-/****************************************************
  * Socketテーブルに関する宣言
  ***************************************************/
 
-#define cSocketTbl_initialize(i_inst,buf) NyLPC_cPtrTbl_initialize(i_inst,buf,NyLPC_cIPv4_MAX_TCP_SOCKET)
-
+#define cSocketTbl_initialize(i_inst,buf) NyLPC_cPtrTbl_initialize(i_inst,buf,NyLPC_cIPv4_MAX_SOCKET)
+#define cSocketTbl_finalize(i_inst)
 
 /**
- * 条件に一致する、アクティブなソケットオブジェクトを取得します。
+ * 条件に一致する、アクティブなTCPソケットオブジェクトを取得します。
  * この関数は、ローカルIPが一致していると仮定して検索をします。
  * @param i_rip
  * リモートIPアドレスを指定します。
  */
-static NyLPC_TcTcpSocket_t* cSocketTbl_getMatchSocket(
+static NyLPC_TcTcpSocket_t* cSocketTbl_getMatchTcpSocket(
     NyLPC_TcPtrTbl_t* i_inst,
     NyLPC_TUInt16 i_lport,
     struct NyLPC_TIPv4Addr i_rip,
     NyLPC_TUInt16 i_rport)
 {
-    NyLPC_TcTcpSocket_t** p=(NyLPC_TcTcpSocket_t**)(i_inst->buf);
+    NyLPC_TcBaseSocket_t** p=(NyLPC_TcBaseSocket_t**)(i_inst->buf);
+    NyLPC_TcTcpSocket_t* tp;
+    int i;
+    //一致するポートを検索
+    for(i=i_inst->size-1;i>=0;i--){
+        if(p[i]==NULL || p[i]->_typeid!=NyLPC_TcBaseSocket_TYPEID_TCP_SOCK){
+            continue;
+        }
+        tp=(NyLPC_TcTcpSocket_t*)p[i];
+        if(tp->tcpstateflags==UIP_CLOSED){
+            continue;
+        }
+        //パラメータの一致チェック
+        if(i_lport!=tp->uip_connr.lport || i_rport!= tp->uip_connr.rport || i_rip.v!=tp->uip_connr.ripaddr.v)
+        {
+            continue;
+        }
+        return tp;
+    }
+    return NULL;
+}
+static NyLPC_TcUdpSocket_t* cSocketTbl_getMatchUdpSocket(
+    NyLPC_TcPtrTbl_t* i_inst,
+    NyLPC_TUInt16 i_lport)
+{
+    NyLPC_TcBaseSocket_t** p=(NyLPC_TcBaseSocket_t**)(i_inst->buf);
+    NyLPC_TcUdpSocket_t* tp;
+    int i;
+    //一致するポートを検索
+    for(i=i_inst->size-1;i>=0;i--){
+        if(p[i]==NULL || p[i]->_typeid!=NyLPC_TcBaseSocket_TYPEID_UDP_SOCK){
+            continue;
+        }
+        tp=(NyLPC_TcUdpSocket_t*)p[i];
+        //パラメータの一致チェック
+        if(i_lport!=tp->uip_udp_conn.lport)
+        {
+            continue;
+        }
+        return tp;
+    }
+    return NULL;
+}
+static NyLPC_TcUdpSocket_t* cSocketTbl_getMatchMulticastUdpSocket(
+    NyLPC_TcPtrTbl_t* i_inst,
+    struct NyLPC_TIPv4Addr* i_mcast_ip,
+    NyLPC_TUInt16 i_lport)
+{
+    NyLPC_TcBaseSocket_t** p=(NyLPC_TcBaseSocket_t**)(i_inst->buf);
+    NyLPC_TcUdpSocket_t* tp;
+    int i;
+    //一致するポートを検索
+    for(i=i_inst->size-1;i>=0;i--){
+        if(p[i]==NULL || p[i]->_typeid!=NyLPC_TcBaseSocket_TYPEID_UDP_SOCK){
+            continue;
+        }
+        tp=(NyLPC_TcUdpSocket_t*)p[i];
+        //パラメータの一致チェック
+        if(i_lport!=tp->uip_udp_conn.lport || NyLPC_TIPv4Addr_isEqual(i_mcast_ip,&(tp->uip_udp_conn.lipaddr)))
+        {
+            continue;
+        }
+        return tp;
+    }
+    return NULL;
+}
+
+/**
+ * i_peer番号に一致するリスナを返します。
+ */
+static NyLPC_TcTcpListener_t* cSocketTbl_getListenerByPeerPort(NyLPC_TcPtrTbl_t* i_inst,NyLPC_TUInt16 i_peer_port)
+{
+    NyLPC_TcBaseSocket_t** p=(NyLPC_TcBaseSocket_t**)(i_inst->buf);
+    NyLPC_TcTcpListener_t* lp;
     int i;
     //一致するポートを検索して、acceptをコールする。
     for(i=i_inst->size-1;i>=0;i--){
-        if(p[i]==NULL){
-            continue;
-        }
-        if(p[i]->tcpstateflags==UIP_CLOSED){
+        if(p[i]==NULL || p[i]->_typeid!=NyLPC_TcBaseSocket_TYPEID_TCP_LISTENER){
             continue;
         }
-        //パラメータの一致チェック
-        if(i_lport!=p[i]->uip_connr.lport || i_rport!= p[i]->uip_connr.rport || i_rip.v!=p[i]->uip_connr.ripaddr.v)
-        {
+        lp=(NyLPC_TcTcpListener_t*)p[i];
+        if(lp->_port!=i_peer_port){
             continue;
         }
-        return p[i];
+        return lp;
     }
     return NULL;
 }
+
 /**
  * テーブルにある有効なソケットのperiodicをすべて呼び出します。
  */
 static void cSocketTbl_callPeriodic(
     NyLPC_TcPtrTbl_t* i_inst)
 {
-    NyLPC_TcTcpSocket_t** p=(NyLPC_TcTcpSocket_t**)(i_inst->buf);
+    NyLPC_TcBaseSocket_t** p=(NyLPC_TcBaseSocket_t**)(i_inst->buf);
+    int i;
+    for(i=i_inst->size-1;i>=0;i--){
+        if(p[i]==NULL){
+            continue;
+        }
+        switch(p[i]->_typeid){
+        case NyLPC_TcBaseSocket_TYPEID_TCP_SOCK:
+            //downcast!
+            NyLPC_cTcpSocket_periodic((NyLPC_TcTcpSocket_t*)(p[i]));
+            break;
+        case NyLPC_TcBaseSocket_TYPEID_UDP_SOCK:
+            NyLPC_cUdpSocket_periodic((NyLPC_TcUdpSocket_t*)(p[i]));
+            break;
+        default:
+            continue;
+        }
+    }
+}
+
+/**
+ * テーブルにある有効なソケットのstartを全て呼び出します。
+ */
+static void cSocketTbl_callSocketStart(
+    NyLPC_TcPtrTbl_t* i_inst,
+    const NyLPC_TcIPv4Config_t* i_cfg)
+{
+    NyLPC_TcBaseSocket_t** p=(NyLPC_TcBaseSocket_t**)(i_inst->buf);
     int i;
     for(i=i_inst->size-1;i>=0;i--){
         if(p[i]==NULL){
             continue;
         }
-        NyLPC_cTcpSocket_periodic(p[i]);
+        switch(p[i]->_typeid){
+        case NyLPC_TcBaseSocket_TYPEID_UDP_SOCK:
+            NyLPC_cUdpSocket_startService((NyLPC_TcUdpSocket_t*)(p[i]),i_cfg);
+            break;
+        case NyLPC_TcBaseSocket_TYPEID_TCP_SOCK:
+            NyLPC_cTcpSocket_startService((NyLPC_TcTcpSocket_t*)(p[i]),i_cfg);
+            break;
+        default:
+            continue;
+        }
     }
 }
+/**
+ * テーブルにある有効なソケットのstartを全て呼び出します。
+ */
+static void cSocketTbl_callSocketStop(
+    NyLPC_TcPtrTbl_t* i_inst)
+{
+    NyLPC_TcBaseSocket_t** p=(NyLPC_TcBaseSocket_t**)(i_inst->buf);
+    int i;
+    for(i=i_inst->size-1;i>=0;i--){
+        if(p[i]==NULL){
+            continue;
+        }
+        switch(p[i]->_typeid){
+        case NyLPC_TcBaseSocket_TYPEID_UDP_SOCK:
+            NyLPC_cUdpSocket_stopService((NyLPC_TcUdpSocket_t*)(p[i]));
+            break;
+        case NyLPC_TcBaseSocket_TYPEID_TCP_SOCK:
+            NyLPC_cTcpSocket_stopService((NyLPC_TcTcpSocket_t*)(p[i]));
+            break;
+        default:
+            continue;
+        }
+    }
+}
+
+/****************************************************
+ * NyLPC_cIPv4
+ ***************************************************/
 
 /**
  * Static関数
@@ -151,10 +259,9 @@
 static NyLPC_TBool tcp_rx(
     NyLPC_TcIPv4_t* i_inst,
     NyLPC_TcIPv4Payload_t* i_ipp);
-
-/****************************************************
- * NyLPC_cIPv4
- ***************************************************/
+static NyLPC_TBool udp_rx(
+    NyLPC_TcIPv4_t* i_inst,
+    NyLPC_TcIPv4Payload_t* i_ipp);
 
 /**
  * See Header file.
@@ -163,9 +270,10 @@
     NyLPC_TcIPv4_t* i_inst)
 {
     //内部テーブルの初期化
-    cListenerTbl_initialize(&(i_inst->_listener_tbl),(void**)(i_inst->_listener_array_buf));
     cSocketTbl_initialize(&(i_inst->_socket_tbl),(void**)(i_inst->_socket_array_buf));
     //instanceの初期化
+    NyLPC_cMutex_initialize(&(i_inst->_sock_mutex));
+    NyLPC_cMutex_initialize(&(i_inst->_listener_mutex));
     i_inst->_ref_config=NULL;
     return;
 }
@@ -176,6 +284,9 @@
 void NyLPC_cIPv4_finalize(
     NyLPC_TcIPv4_t* i_inst)
 {
+    cSocketTbl_finalize(&(i_inst->_socket_tbl));
+    NyLPC_cMutex_finalize(&(i_inst->_sock_mutex));
+    NyLPC_cMutex_finalize(&(i_inst->_listener_mutex));
     return;
 }
 
@@ -189,6 +300,8 @@
     NyLPC_ArgAssert(i_ref_configlation!=NULL);
     //リストの初期化、ここでするべき?しないべき?
     i_inst->_ref_config=i_ref_configlation;
+    //configulationのアップデートを登録されてるソケットに通知
+    cSocketTbl_callSocketStart(&(i_inst->_socket_tbl),i_ref_configlation);
     return;
 }
 
@@ -198,8 +311,7 @@
 void NyLPC_cIPv4_stop(
     NyLPC_TcIPv4_t* i_inst)
 {
-    //実行タイミングが未設計。当分は使わないこと。
-    //新規ソケットの生成を打ち切って、すべてのソケットが停止するのを待つ?
+    cSocketTbl_callSocketStop(&(i_inst->_socket_tbl));
     i_inst->_ref_config=NULL;
     return;
 }
@@ -209,7 +321,7 @@
  */
 NyLPC_TBool NyLPC_cIPv4_addSocket(
     NyLPC_TcIPv4_t* i_inst,
-    NyLPC_TcTcpSocket_t* i_sock)
+    NyLPC_TcBaseSocket_t* i_sock)
 {
     //当面、stop中しか成功しない。
     NyLPC_Assert(!NyLPC_cUipService_isRun());
@@ -221,7 +333,7 @@
  */
 NyLPC_TBool NyLPC_cIPv4_removeSocket(
     NyLPC_TcIPv4_t* i_inst,
-    NyLPC_TcTcpSocket_t* i_sock)
+    NyLPC_TcBaseSocket_t* i_sock)
 {
     NyLPC_TInt16 i;
     NyLPC_Assert(!NyLPC_cUipService_isRun());
@@ -233,38 +345,6 @@
     return NyLPC_TBool_FALSE;
 }
 
-/**
- * See header file.
- */
-NyLPC_TBool NyLPC_cIPv4_addListener(
-    NyLPC_TcIPv4_t* i_inst,
-    NyLPC_TcTcpListener_t* i_listener)
-{
-    //当面、stop中しか成功しない。
-    NyLPC_Assert(!NyLPC_cUipService_isRun());
-    return NyLPC_cPtrTbl_add(&(i_inst->_listener_tbl),i_listener)>=0;
-}
-
-/**
- * See header file.
- */
-NyLPC_TBool NyLPC_cIPv4_removeListener(
-    NyLPC_TcIPv4_t* i_inst,
-    NyLPC_TcTcpListener_t* i_listener)
-{
-    NyLPC_TInt16 i;
-    NyLPC_Assert(!NyLPC_cUipService_isRun());
-    i=NyLPC_cPtrTbl_getIndex(&(i_inst->_listener_tbl),i_listener);
-    if(i>=0){
-        NyLPC_cPtrTbl_remove(&(i_inst->_listener_tbl),i);
-        return NyLPC_TBool_TRUE;
-    }
-    return NyLPC_TBool_FALSE;
-}
-
-
-
-
 
 #define IS_START(i_inst) ((i_inst)->_ref_config!=NULL)
 
@@ -306,8 +386,9 @@
         //TCP受信処理
         return tcp_rx(i_inst,&ipv4);
     case UIP_PROTO_UDP:
-        //  //uip_process_UDP();//実装したら解除いして
-        NyLPC_OnErrorGoto(ERROR_DROP);
+        //UDP処理
+        udp_rx(i_inst,&ipv4);//r
+        return NyLPC_TBool_FALSE;
     case UIP_PROTO_ICMP:
         if(!NyLPC_cIPv4IComp_rx(&(inst->_icomp),&ipv4)){
             NyLPC_OnErrorGoto(ERROR_DROP);
@@ -346,8 +427,8 @@
         //受信エラーのあるパケットはドロップ
         goto DROP;
     }
-    //アクティブなソケットを探す。
-    sock=cSocketTbl_getMatchSocket(&(i_inst->_socket_tbl),i_ipp->payload.tcp->destport,i_ipp->header->srcipaddr,i_ipp->payload.tcp->srcport);
+    //アクティブなTCPソケットを探す。
+    sock=cSocketTbl_getMatchTcpSocket(&(i_inst->_socket_tbl),i_ipp->payload.tcp->destport,i_ipp->header->srcipaddr,i_ipp->payload.tcp->srcport);
     if(sock!=NULL)
     {
         //既存の接続を処理
@@ -361,20 +442,18 @@
             return NyLPC_TBool_TRUE;
         }
         //このポートに対応したListenerを得る。
-        listener=cListenerTbl_getByPeerPort(&(i_inst->_listener_tbl),i_ipp->payload.tcp->destport);
+        listener=cSocketTbl_getListenerByPeerPort(&(i_inst->_socket_tbl),i_ipp->payload.tcp->destport);
         if(listener==NULL){
             //Listen対象ではない。RST送信
             NyLPC_cIPv4Payload_setTcpReverseRstAck(i_ipp);
             return NyLPC_TBool_TRUE;
         }
         //リスナにソケットのバインドを依頼する。
-        sock=NyLPC_cTcpListener_makeSynRcvdSocket(listener,i_inst->_ref_config,i_ipp);
+        sock=NyLPC_cTcpListener_makeSynRcvdSocket(listener,i_ipp);
         if(sock==NULL){
             //Listen失敗。ドロップ
             goto DROP;
         }
-//      //Socketの割当に成功。管理リストへ追加
-//      NyLPC_AbortIfNot(NyLPC_cPtrTbl_add(&(i_inst->_socket_tbl),sock)>=0);
         return NyLPC_TBool_FALSE;//LISTEN成功。送信データなし
     }
     return NyLPC_TBool_TRUE;
@@ -384,6 +463,53 @@
 
 
 
+static NyLPC_TBool udp_rx(
+    NyLPC_TcIPv4_t* i_inst,
+    NyLPC_TcIPv4Payload_t* i_ipp)
+{
+    NyLPC_TcUdpSocket_t* sock;
+    //Multicastか調べる
+    if(NyLPC_TIPv4Addr_isEqualWithMask(&(i_ipp->header->destipaddr),&NyLPC_TIPv4Addr_MULTICAST,&NyLPC_TIPv4Addr_MULTICAST_MASK)){
+        //Multicastパケット
+
+        //チェックサムの計算
+        if((NyLPC_TIPv4Header_makeTcpChecksum(i_ipp->header) != 0xffff))
+        {
+            //受信エラーのあるパケットはドロップ
+            goto DROP;
+        }
+        //マルチキャストに参加している&&portの一致するソケットを検索
+        sock=cSocketTbl_getMatchMulticastUdpSocket(&(i_inst->_socket_tbl),&(i_ipp->header->destipaddr),i_ipp->payload.udp->destport);
+        if(sock==NULL)
+        {
+            goto DROP;
+        }
+    }else{
+        //ユニキャストパケット
+
+        //自分自身のIPに対する呼び出し?
+        if(!NyLPC_TIPv4Addr_isEqual(&(i_ipp->header->destipaddr),&(i_inst->_ref_config->ip_addr)))
+        {
+            //自分以外のパケットはドロップ
+            goto DROP;
+        }
+        //チェックサムの計算
+        if((NyLPC_TIPv4Header_makeTcpChecksum(i_ipp->header) != 0xffff))
+        {
+            //受信エラーのあるパケットはドロップ
+            goto DROP;
+        }
+        //ポートの一致するUDPソケットを探す。
+        sock=cSocketTbl_getMatchUdpSocket(&(i_inst->_socket_tbl),i_ipp->payload.udp->destport);
+        if(sock==NULL)
+        {
+            goto DROP;
+        }
+    }
+    //既存の接続を処理
+    return NyLPC_cUdpSocket_parseRx(sock,i_ipp);
+DROP:
+    return NyLPC_TBool_FALSE;
+}
 
 
-