Ryo Iizuka / libMiMic

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

Revision:
37:fc4b4fd6a649
Parent:
21:f2a70f15301f
Child:
48:00d211aac2ec
diff -r f02596009a02 -r fc4b4fd6a649 core/uip/NyLPC_cUipService.c
--- a/core/uip/NyLPC_cUipService.c	Thu May 16 16:06:46 2013 +0000
+++ b/core/uip/NyLPC_cUipService.c	Wed Jun 19 09:33:01 2013 +0000
@@ -52,6 +52,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
+#include "NyLPC_cUipService_protected.h"
 #include "NyLPC_cIPv4IComp_protected.h"
 #include "NyLPC_cTcpListener_protected.h"
 #include "NyLPC_stdlib.h"
@@ -137,7 +138,6 @@
 
 NyLPC_TBool NyLPC_cUipService_initialize(void)
 {
-
     NyLPC_TcUipService_t* inst=&_service_instance;
     //サービスは停止している事。 - Service must be uninitialized.
     NyLPC_Assert(!NyLPC_TcUipService_isInitService());
@@ -156,18 +156,9 @@
     NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(inst->_mutex)));
 
     _NyLPC_TcUipService_inst=inst;
-    inst->stx.h.is_lock=NyLPC_TUInt8_FALSE;
-    inst->stx.h.ref=0;
     //タスク起動
     NyLPC_cThread_initialize(&th,NyLPC_TcUipService_config_STACK_SIZE,NyLPC_TcThread_PRIORITY_SERVICE);
     NyLPC_cThread_start(&th,uipTask,NULL);
-//  NyLPC_AbortIfNot(pdPASS==xTaskCreate(
-//      uipTask,
-//      (signed char*)NyLPC_TcUipService_config_TASK_NAME,
-//      NyLPC_TcUipService_config_STACK_SIZE,
-//      ( void * ) NULL,
-//      NyLPC_TcUipService_config_TASK_PRIORITY,
-//      (void*)_NyLPC_TcUipService_inst));
     return NyLPC_TBool_TRUE;
 }
 
@@ -274,6 +265,8 @@
 #define PERIODIC_TIMER (1*200)
 #define ARP_TIMER (60*1000*10)
 
+
+
 /**
  * 操作キューを確認して、タスクのステータスをアップデートします。
  * 高速化のため、Proc-Callerを使用していません。複雑なタスク操作をするときには、書き換えてください。
@@ -307,6 +300,10 @@
         NyLPC_cIPv4Arp_initialize(&(inst->_arp),inst->_ref_config);
         NyLPC_cStopwatch_startExpire(&(inst->_arp_sw),1);//1度ARPを起動するため。
         NyLPC_cStopwatch_startExpire(&(inst->_periodic_sw),PERIODIC_TIMER);
+        //InBuffer初期化
+        inst->stx.h.is_lock=NyLPC_TUInt8_FALSE;
+        inst->stx.h.ref=0;
+        //EtherNETデバイス初期化
         while(!inst->_ethif->start(&(inst->_ref_config->eth_mac)));
         inst->_status=NyLPC_TcUipService_STATUS_RUN;
         break;
@@ -320,6 +317,7 @@
         inst->_ethif->stop();
         NyLPC_cIPv4_stop(&(inst->_tcpv4));
         NyLPC_cIPv4IComp_finalize(&(inst->_icomp));
+        NyLPC_cIPv4Arp_finalize(&(inst->_arp));
         inst->_status=NyLPC_TcUipService_STATUS_STOP;
         break;
     default:
@@ -409,7 +407,9 @@
             NyLPC_cStopwatch_startExpire(&(inst->_arp_sw),ARP_TIMER);
         }
         if(NyLPC_cStopwatch_isExpired(&(inst->_periodic_sw))){
+            NyLPC_cMutex_unlock(&(inst->_mutex));
             NyLPC_cIPv4_periodec(&(inst->_tcpv4));
+            NyLPC_cMutex_lock(&(inst->_mutex));
             NyLPC_cStopwatch_startExpire(&(inst->_periodic_sw),PERIODIC_TIMER);
         }
         //リソースロックの解除
@@ -442,8 +442,35 @@
     NyLPC_cMutex_unlock(&(inst->_mutex));
     return;
 }
+/**
+ * 指定したIPアドレスに対してARPRequestを送信します。
+ */
+void NyLPC_cUipService_sendArpRequest(const struct NyLPC_TIPv4Addr* i_addr)
+{
+    NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst;
+    NyLPC_TUInt16 tx_len;
+    struct TEthPacket* ethbuf;
+    //ACK送信用の自己バッファが空くまで待つ
+    while(inst->stx.h.is_lock){
+        inst->_ethif->processTx();
+    }
+    //ARPパケットを作る。
+    ethbuf=(struct TEthPacket*)(inst->stx.buf);
+    NyLPC_TArpHeader_setArpRequest(&(ethbuf->data.arp),inst->_ref_config->ip_addr,&(inst->_ref_config->eth_mac),*i_addr);
+    tx_len=NyLPC_TEthernetIIHeader_setArpTx(&(ethbuf->header),&(inst->_ref_config->eth_mac));
+    //送信
+    inst->_ethif->sendTxEthFrame(&(inst->stx.h),tx_len);
+    return;
+}
 
-
+/**
+ * ARPテーブルに指定したIPがあるかを返します。
+ */
+NyLPC_TBool NyLPC_cUipService_hasArpInfo(const struct NyLPC_TIPv4Addr* i_addr)
+{
+    NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst;
+    return NyLPC_cIPv4Arp_IPv4toEthAddr(&inst->_arp,*i_addr)!=NULL;
+}
 
 
 /**
@@ -452,14 +479,17 @@
  * @param i_hint
  * 取得したいメモリサイズを指定します。(このサイズは、イーサネットヘッダのサイズを含みません。)
  * このサイズよりも小さなサイズが割り当てられることがあります。
+ * @param o_size
+ * イーサネットヘッダを除いたペイロード部分の長さ
  * @return
  * 成功:IPペイロードのためのメモリブロックを返します。/失敗:NULL
+ * 返されるメモリはブロックの[TEthPacket][payload]の構造で、[payload]のアドレスが返されます。
  */
 void* NyLPC_cUipService_allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
 {
-    //排他処理をして、メモリを取得する。
     NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst;
     struct NyLPC_TTxBufferHeader* ethbuf;
+    //排他処理をして、メモリを取得する。
     NyLPC_cMutex_lock(&(inst->_mutex));
     ethbuf=(struct NyLPC_TTxBufferHeader*)inst->_ethif->allocTxBuf(i_hint+sizeof(struct NyLPC_TEthernetIIHeader),o_size);
     NyLPC_cMutex_unlock(&(inst->_mutex));
@@ -562,6 +592,20 @@
     return;
 }
 
+/**
+ * マルチキャスとアドレスへ変換する。
+ */
+static void ip2MulticastEmacAddr(const struct NyLPC_TIPv4Addr* i_addr,struct NyLPC_TEthAddr* o_emac)
+{
+    NyLPC_TUInt32 n=NyLPC_htonl(i_addr->v);
+    o_emac->addr[0]=0x01;
+    o_emac->addr[1]=0x00;
+    o_emac->addr[2]=0x5E;
+    o_emac->addr[3]=((n>>16) & 0x7f);
+    o_emac->addr[4]=((n>> 8) & 0xff);
+    o_emac->addr[5]=(n & 0xff);
+    return;
+};
 
 /**
  * ペイロードをIPパケットとしてネットワークへ送出します。
@@ -573,23 +617,32 @@
 static NyLPC_TBool sendIPv4Tx(struct NyLPC_TTxBufferHeader* i_eth_buf)
 {
     NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst;
+    struct NyLPC_TEthAddr emac;
     NyLPC_TUInt16 tx_len;
+    const struct NyLPC_TEthAddr* eth_dest;
     struct TEthPacket* ethbuf=(struct TEthPacket*)(i_eth_buf+1);
-NyLPC_Trace();
     //ペイロードのアドレスから、イーサネットフレームバッファのアドレスを復元
-    //const struct NyLPC_TEthAddr* eth_dest=uip_arp_IPv4toEthAddr(ethbuf->data.ipv4.destipaddr);
-    const struct NyLPC_TEthAddr* eth_dest=NyLPC_cIPv4Arp_IPv4toEthAddr(&inst->_arp,ethbuf->data.ipv4.destipaddr);
-    //IP->MAC変換をテスト。
-    if(eth_dest==NULL){
-        //失敗
-NyLPC_Trace();
-        return NyLPC_TBool_FALSE;
+
+    if(NyLPC_TIPv4Addr_isEqual(&(ethbuf->data.ipv4.destipaddr),&NyLPC_TIPv4Addr_BROADCAST)) {
+        //ブロードキャストならそのまま
+        eth_dest=&NyLPC_TEthAddr_BROADCAST;
+    }else if(NyLPC_TIPv4Addr_isEqualWithMask(&(ethbuf->data.ipv4.destipaddr),&NyLPC_TIPv4Addr_MULTICAST,&NyLPC_TIPv4Addr_MULTICAST_MASK)){
+        //マルチキャスト
+        ip2MulticastEmacAddr(&(ethbuf->data.ipv4.destipaddr),&emac);
+        eth_dest=&emac;
+    }else{
+        //LocalIP以外ならdefaultRootへ変換
+        eth_dest=NyLPC_cIPv4Arp_IPv4toEthAddr(
+            &inst->_arp,
+            NyLPC_cIPv4Config_isLocalIP(inst->_ref_config, &(ethbuf->data.ipv4.destipaddr))?(ethbuf->data.ipv4.destipaddr):(inst->_ref_config->dr_addr));
+        //IP->MAC変換をテスト。
+        if(eth_dest==NULL){
+            return NyLPC_TBool_FALSE;
+        }
     }
-NyLPC_Trace();
     //変換可能なら、イーサネットヘッダを更新して、送信処理へ。
     tx_len=NyLPC_TEthernetIIHeader_setIPv4Tx(&(ethbuf->header),&(inst->_ref_config->eth_mac),eth_dest);
     inst->_ethif->sendTxEthFrame(i_eth_buf,tx_len);
-NyLPC_Trace();
     return NyLPC_TBool_TRUE;
 }