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_cMiMicIpNetIf.c Source File

NyLPC_cMiMicIpNetIf.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  * Parts of this file were leveraged from uIP:
00027  *
00028  * Copyright (c) 2001-2003, Adam Dunkels.
00029  * All rights reserved.
00030  *
00031  * Redistribution and use in source and binary forms, with or without
00032  * modification, are permitted provided that the following conditions
00033  * are met:
00034  * 1. Redistributions of source code must retain the above copyright
00035  *    notice, this list of conditions and the following disclaimer.
00036  * 2. Redistributions in binary form must reproduce the above copyright
00037  *    notice, this list of conditions and the following disclaimer in the
00038  *    documentation and/or other materials provided with the distribution.
00039  * 3. The name of the author may not be used to endorse or promote
00040  *    products derived from this software without specific prior
00041  *    written permission.
00042  *
00043  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00044  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00045  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00046  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00047  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00048  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00049  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00050  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00051  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00052  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00053  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00054  */
00055 //#include "NyLPC_cIPv4IComp_protected.h"
00056 //#include "NyLPC_cTcpListener_protected.h"
00057 #include "NyLPC_cMiMicIpNetIf_protected.h"
00058 #include "NyLPC_stdlib.h"
00059 #include "../NyLPC_NetIf_ip_types.h"
00060 #include "NyLPC_cIPv4IComp_protected.h"
00061 #include "NyLPC_cMiMicIpTcpSocket_protected.h"
00062 #include "NyLPC_cMiMicIpUdpSocket_protected.h"
00063 #include "NyLPC_cMiMicIpTcpListener_protected.h"
00064 
00065 
00066 
00067 
00068 
00069 /****************************************************
00070  * UipServiceに関する宣言:その他
00071  ***************************************************/
00072 /**
00073  * イーサネットフレームの読み出し構造体
00074  */
00075 struct TEthPacket
00076 {
00077     struct NyLPC_TEthernetIIHeader header;
00078     union{
00079         struct NyLPC_TArpHeader arp;
00080         struct NyLPC_TIPv4Header ipv4;
00081     }data;
00082 }PACK_STRUCT_END;
00083 
00084 
00085 
00086 /**
00087  * サービスインスタンスのポインタ。サービスが稼働中はインスタンスのポインタが有効です。
00088  */
00089 NyLPC_TcMiMicIpNetIf_t* _NyLPC_TcMiMicIpNetIf_inst=NULL;
00090 
00091 
00092 
00093 /**
00094  * uipタスク
00095  */
00096 static int uipTask(void *pvParameters);
00097 
00098 /** イーサネットドライバからのハンドラ*/
00099 static void ethernet_handler(void* i_param,NyLPC_TiEthernetDevice_EVENT i_type);
00100 
00101 //--------------------------------------------------------------
00102 
00103 
00104 static NyLPC_TBool sendIPv4Tx(struct TEthPacket* i_eth_buf);
00105 
00106 //static void sendArpReqest(const struct TEthPacket* i_eth_packet);
00107 static void sendRawEthFrameNL(void* i_buf,NyLPC_TUInt16 i_len);
00108 static void releaseTxBufNL(void* i_buf);
00109 
00110 /**メッセージなし*/
00111 #define TTaskMessage_MSG_NULL    0x0000
00112 /**uipコアタスクに、開始要求する*/
00113 #define TTaskMessage_MSG_RUN     0x0001
00114 /**uipコアタスクに、停止要求する*/
00115 #define TTaskMessage_MSG_STOP    0x0002
00116 
00117 
00118 static NyLPC_TcThread_t th;
00119 
00120 NyLPC_TBool NyLPC_cMiMicIpNetIf_initialize(NyLPC_TcMiMicIpNetIf_t* i_inst)
00121 {
00122     //サービスは停止している事。 - Service must be uninitialized.
00123     NyLPC_Assert(!NyLPC_cMiMicIpNetIf_isInitService());
00124     //IP処理部分の初期化
00125     NyLPC_cIPv4_initialize(&(i_inst->_tcpv4));
00126     //EMAC割込セマフォ
00127     NyLPC_cSemaphore_initialize(&i_inst->_emac_semapho);
00128 
00129     i_inst->_status=0x00;
00130     NyLPC_cStopwatch_initialize(&(i_inst->_arp_sw));
00131     NyLPC_cStopwatch_initialize(&(i_inst->_periodic_sw));
00132     NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(i_inst->_mutex)));
00133 
00134     _NyLPC_TcMiMicIpNetIf_inst=i_inst;
00135     //タスク起動
00136     NyLPC_cThread_initialize(&th,NyLPC_cMiMicIpNetIf_config_STACK_SIZE,NyLPC_TcThread_PRIORITY_SERVICE);
00137     NyLPC_cThread_start(&th,uipTask,NULL);
00138     return NyLPC_TBool_TRUE;
00139 }
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 /**
00148  * UIP処理を開始します。
00149  * この関数はリエントラントではありません。複数のタスクから共有するときには、排他ロックを掛けてください。
00150  * @param i_ref_config
00151  * このコンフィギュレーションは、stopを実行するまでの間、インスタンスから参照します。外部で保持してください。
00152  */
00153 void NyLPC_cMiMicIpNetIf_start(const NyLPC_TcIPv4Config_t* i_ref_config)
00154 {
00155     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00156     NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService());
00157     if(!NyLPC_cMiMicIpNetIf_isRun())
00158     {
00159         //はじめて起動するときに1度だけデバイス取得(タスクスイッチが動いてないと動かないからここで。)
00160         if(inst->_ethif==NULL){
00161             inst->_ethif=getEthernetDevicePnP();
00162         }
00163         //コンフィグレーションセット
00164         inst->_netinfo.current_config=i_ref_config;
00165         //開始要求セット
00166         NyLPC_TUInt16_setBit(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_START);
00167         //Order実行待ち
00168         while(NyLPC_TUInt16_isBitOn(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_START)){
00169             NyLPC_cThread_sleep(10);
00170         }
00171         //デバイス情報の追記
00172         inst->_netinfo.device_name=NyLPC_iEthernetDevice_getDevicName(inst->_ethif);
00173     }
00174     return;
00175 }
00176 /**
00177  * UIP処理を停止します。
00178  * この関数はリエントラントではありません。複数のタスクから共有するときには、排他ロックを掛けてください。
00179  * いまのところ、ストップシーケンスの実装は良くありません。
00180  * 再設計が必要。
00181  */
00182 void NyLPC_cMiMicIpNetIf_stop(void)
00183 {
00184     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00185     NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService());
00186     if(NyLPC_cMiMicIpNetIf_isRun())
00187     {
00188         NyLPC_TUInt16_setBit(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_STOP);
00189         //Order実行待ち
00190         while(NyLPC_TUInt16_isBitOn(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_STOP)){
00191             NyLPC_cThread_sleep(10);
00192         }
00193     }
00194     return;
00195 }
00196 
00197 static const struct NyLPC_TNetInterfaceInfo* NyLPC_cMiMicIpNetIf_getInterfaceInfo(void)
00198 {
00199     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00200     return &inst->_netinfo;
00201 }
00202 
00203 /**********************************************************************
00204  *
00205  * </HWコールバックに関わる宣言>
00206  *
00207  *********************************************************************/
00208 
00209 
00210 //PERIODIC rate
00211 #define PERIODIC_TIMER (1*200)
00212 #define ARP_TIMER (60*1000*10)
00213 
00214 
00215 
00216 /**
00217  * 操作キューを確認して、タスクのステータスをアップデートします。
00218  * 高速化のため、Proc-Callerを使用していません。複雑なタスク操作をするときには、書き換えてください。
00219  * @return
00220  * UIPタスクの実行状態
00221  */
00222 static NyLPC_TBool updateTaskStatus()
00223 {
00224     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00225     if(NyLPC_cMiMicIpNetIf_isRun()){
00226         //開始状態
00227         if(NyLPC_TUInt16_isBitOn(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_STOP))
00228         {
00229             //停止操作
00230             NyLPC_iEthernetDevice_stop(inst->_ethif);
00231             NyLPC_cIPv4_stop(&(inst->_tcpv4));
00232             NyLPC_cIPv4IComp_finalize(&(inst->_icomp));
00233             NyLPC_cIPv4Arp_finalize(&(inst->_arp));
00234 //            inst->_ref_config=NULL;
00235             NyLPC_TUInt16_unsetBit(inst->_status,NyLPC_TcMiMicIpNetIf_STATUSBIT_IS_RUNNING);
00236             NyLPC_TUInt16_unsetBit(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_STOP);
00237             return NyLPC_TBool_FALSE;
00238         }
00239         return NyLPC_TBool_TRUE;
00240     }else{
00241         //停止状態
00242         if(NyLPC_TUInt16_isBitOn(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_START))
00243         {
00244             //TCP,ICOMPの初期化
00245             NyLPC_cIPv4_start(&(inst->_tcpv4),inst->_netinfo.current_config);
00246             NyLPC_cIPv4IComp_initialize(&(inst->_icomp),inst->_netinfo.current_config);
00247             //uip_arp_init(msg->start.ref_config);
00248             NyLPC_cIPv4Arp_initialize(&(inst->_arp),inst->_netinfo.current_config);
00249             NyLPC_cStopwatch_startExpire(&(inst->_arp_sw),1);//1度ARPを起動するため。
00250             NyLPC_cStopwatch_startExpire(&(inst->_periodic_sw),PERIODIC_TIMER);
00251             //EtherNETデバイス初期化
00252             while(!NyLPC_iEthernetDevice_start(inst->_ethif,&(inst->_netinfo.current_config->eth_mac),ethernet_handler,inst));
00253             NyLPC_TUInt16_setBit(inst->_status,NyLPC_TcMiMicIpNetIf_STATUSBIT_IS_RUNNING);
00254             NyLPC_TUInt16_unsetBit(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_START);
00255             return NyLPC_TBool_TRUE;
00256         }
00257         return NyLPC_TBool_FALSE;
00258     }
00259 }
00260 
00261 /**
00262  * uipタスクのメインループ
00263  */
00264 static int uipTask(void *pvParameters)
00265 {
00266     NyLPC_TUInt16 rx_len,tx_len;
00267     struct TEthPacket* ethbuf;
00268     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00269     void* r;
00270     (void)pvParameters;
00271     for( ;; )
00272     {
00273         //タスク状態の更新
00274         if(!updateTaskStatus())
00275         {
00276             //RUNステータス以外の時は、ここで終了する。
00277             NyLPC_cThread_sleep(50);
00278             continue;
00279         }
00280         //イーサネットフレームの取得
00281         //Ethernet Device Lock(ARPを含む)
00282         NyLPC_cMutex_lock(&(inst->_mutex));
00283         ethbuf= (struct TEthPacket*)NyLPC_iEthernetDevice_getRxEthFrame(inst->_ethif,&rx_len);
00284         tx_len=0;
00285         while(ethbuf != NULL){
00286             if(rx_len>0)
00287             {
00288                 //ペイロードサイズを計算
00289                 rx_len-=sizeof(struct NyLPC_TEthernetIIHeader);
00290                 switch(ethbuf->header.type)
00291                 {
00292                 case NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_IP):
00293                     //ARPテーブルの更新
00294                     //uip_arp_ipin(&(ethbuf->header),ethbuf->data.ipv4.srcipaddr);
00295                     NyLPC_cIPv4Arp_incomingIp(&inst->_arp,&(ethbuf->header),ethbuf->data.ipv4.srcipaddr);
00296                     //Ethernet Device UnLock(NyLPC_cIPv4_rxがallocをコールする可能性があるので一時的にロック解除)
00297                     NyLPC_cMutex_unlock(&(inst->_mutex));
00298                     //IPパケットの処理
00299                     r=NyLPC_cIPv4_rx(&(inst->_tcpv4),&(ethbuf->data.ipv4),rx_len);
00300                     if(r!=NULL){
00301                         //IPパケットとして送信
00302                         NyLPC_cMiMicIpNetIf_sendIPv4Tx(r);
00303                     }
00304                     //ロックの復帰
00305                     NyLPC_cMutex_lock(&(inst->_mutex));
00306                     if(r!=NULL){
00307                         releaseTxBufNL(r);
00308                     }
00309                     break;
00310                 case NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_ARP):
00311                     //Ethernet Device UnLock(NyLPC_cIPv4_rxがallocをコールする可能性があるので一時的にロック解除)
00312                     NyLPC_cMutex_unlock(&(inst->_mutex));
00313                     r=NyLPC_cIPv4Arp_rx(&inst->_arp,&(ethbuf->data.arp),rx_len,&tx_len);
00314                     NyLPC_cMutex_lock(&(inst->_mutex));
00315                     if(r!=NULL){
00316                         sendRawEthFrameNL(r,tx_len);
00317                         releaseTxBufNL(r);
00318                     }
00319                     break;
00320                 case NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_IPV6):
00321                     //uip_process_ipv6();
00322                     break;
00323                 default:
00324                     break;
00325                 }
00326             }
00327             //受信キューを進行。
00328             NyLPC_iEthernetDevice_nextRxEthFrame(inst->_ethif);
00329             //受信処理
00330             ethbuf= (struct TEthPacket*)NyLPC_iEthernetDevice_getRxEthFrame(inst->_ethif,&rx_len);
00331         }
00332         //データが無い。
00333         if(NyLPC_cStopwatch_isExpired(&(inst->_arp_sw))){
00334             //uip_arp_timer();
00335             NyLPC_cIPv4Arp_periodic(&inst->_arp);
00336             NyLPC_cStopwatch_startExpire(&(inst->_arp_sw),ARP_TIMER);
00337         }
00338         if(NyLPC_cStopwatch_isExpired(&(inst->_periodic_sw))){
00339             NyLPC_cMutex_unlock(&(inst->_mutex));
00340             NyLPC_cIPv4_periodec(&(inst->_tcpv4));
00341             NyLPC_cMutex_lock(&(inst->_mutex));
00342             NyLPC_cStopwatch_startExpire(&(inst->_periodic_sw),PERIODIC_TIMER);
00343         }
00344         //リソースロックの解除
00345         NyLPC_cMutex_unlock(&(inst->_mutex));
00346         //割込によるセマフォの解除か、タイムアウトで再開する。(タイムアウト値は周期関数の実行レート以下にすること。)
00347         NyLPC_cSemaphore_take(&(_NyLPC_TcMiMicIpNetIf_inst->_emac_semapho),PERIODIC_TIMER);
00348     }
00349     return 0;
00350 }
00351 
00352 
00353 /**
00354  * イーサネットドライバからのハンドラ
00355  */
00356 static void ethernet_handler(void* i_param,NyLPC_TiEthernetDevice_EVENT i_type)
00357 {
00358     switch(i_type){
00359     case NyLPC_TiEthernetDevice_EVENT_ON_RX:
00360         //受信系のセマフォブロックの解除
00361         NyLPC_cSemaphore_giveFromISR(&(((NyLPC_TcMiMicIpNetIf_t*)i_param)->_emac_semapho));
00362         break;
00363     default:
00364         break;
00365     }
00366 }
00367 
00368 /**
00369  * IPv4パケットのpeerIPを問い合わせるARPパケットを送信します。
00370  * allocを中でコールするから要UNLOCK状態
00371  */
00372 void NyLPC_cMiMicIpNetIf_sendArpRequest(const struct NyLPC_TIPv4Addr* i_addr)
00373 {
00374     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00375     NyLPC_TUInt16 tx_len;
00376     struct TEthPacket* ethbuf;
00377     //システムTXメモリを得てイーサフレームのポインタを復元
00378     ethbuf=(struct TEthPacket*)(((struct NyLPC_TEthernetIIHeader*)NyLPC_cMiMicIpNetIf_allocSysTxBuf()-1));
00379     //ARPパケットを作る。
00380     NyLPC_TArpHeader_setArpRequest(&(ethbuf->data.arp),inst->_netinfo.current_config->ip_addr,&(inst->_netinfo.current_config->eth_mac),i_addr);
00381     tx_len=NyLPC_TEthernetIIHeader_setArpTx(&(ethbuf->header),&(inst->_netinfo.current_config->eth_mac));
00382     //送信
00383     NyLPC_cMutex_lock(&(inst->_mutex));
00384     NyLPC_iEthernetDevice_sendTxEthFrame(inst->_ethif,ethbuf,tx_len);
00385     NyLPC_iEthernetDevice_releaseTxBuf(inst->_ethif,ethbuf);//NyLPC_cMiMicIpNetIf_releaseTxBufの代用だから元のイーサフレームメモリの値で開放
00386     NyLPC_cMutex_unlock(&(inst->_mutex));
00387 }
00388 
00389 
00390 
00391 
00392 /**
00393  * allocTxBufで取得したペイロードメモリを"IPパケットとして"送信します。
00394  * @param i_eth_payload
00395  * [NyLPC_TEthernetIIHeader][payload]メモリの、[payload]のアドレスを指定します。
00396  * 通常は、NyLPC_cUipService_allocTxBufの返却したメモリを指定します。
00397  */
00398 
00399 void NyLPC_cMiMicIpNetIf_sendIPv4Tx(void* i_eth_payload)
00400 {
00401     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00402     void* p=((struct NyLPC_TEthernetIIHeader*)i_eth_payload)-1;
00403     NyLPC_cMutex_lock(&(inst->_mutex));
00404     //IPパケットの送信を試行
00405     if(sendIPv4Tx((struct TEthPacket*)p)){
00406         NyLPC_cMutex_unlock(&(inst->_mutex));
00407         return;
00408     }
00409     NyLPC_cMutex_unlock(&(inst->_mutex));
00410     //ARPリクエストを代わりに送信
00411     NyLPC_cMiMicIpNetIf_sendArpRequest(&((struct NyLPC_TIPv4Header*)i_eth_payload)->destipaddr);
00412     return;
00413 }
00414 
00415 
00416 /**
00417  * ARPテーブルに指定したIPがあるかを返します。
00418  */
00419 NyLPC_TBool NyLPC_cMiMicIpNetIf_hasArpInfo(const struct NyLPC_TIPv4Addr* i_addr)
00420 {
00421     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00422     return NyLPC_cIPv4Arp_IPv4toEthAddr(&inst->_arp,*i_addr)!=NULL;
00423 }
00424 
00425 /**
00426  * システム用の送信ペイロードを返します。
00427  * 関数は必ず成功します。
00428  */
00429 void* NyLPC_cMiMicIpNetIf_allocSysTxBuf(void)
00430 {
00431     NyLPC_TUInt16 s;
00432     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00433     struct TEthPacket* ethbuf;
00434     //排他処理をして、メモリを取得する。SYSTEMメモリはEthernetドライバの解放待ちのみなのでまとめてLOCKしておk
00435     NyLPC_cMutex_lock(&(inst->_mutex));
00436     for(;;){
00437         ethbuf=(struct TEthPacket*)NyLPC_iEthernetDevice_allocTxBuf(inst->_ethif,NyLPC_TcEthernetMM_HINT_CTRL_PACKET,&s);
00438         if(ethbuf==NULL){
00439             NyLPC_cThread_yield();
00440             continue;
00441         }
00442         break;
00443     }
00444     NyLPC_cMutex_unlock(&(inst->_mutex));
00445     //イーサネットバッファのアドレスを計算
00446     return &(ethbuf->data);
00447 }
00448 
00449 
00450 
00451 void* NyLPC_cMiMicIpNetIf_allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
00452 {
00453     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00454     struct TEthPacket* ethbuf;
00455     //排他処理をして、メモリを取得する。
00456     NyLPC_cMutex_lock(&(inst->_mutex));
00457     ethbuf=(struct TEthPacket*)NyLPC_iEthernetDevice_allocTxBuf(inst->_ethif,i_hint+sizeof(struct NyLPC_TEthernetIIHeader),o_size);
00458     NyLPC_cMutex_unlock(&(inst->_mutex));
00459     if(ethbuf==NULL){
00460         return NULL;
00461     }
00462     //イーサネットバッファのサイズを計算
00463     *o_size-=sizeof(struct NyLPC_TEthernetIIHeader);
00464     //イーサネットバッファのアドレスを計算
00465     return &(ethbuf->data);
00466 }
00467 
00468 
00469 void* NyLPC_cMiMicIpNetIf_releaseTxBuf(void* i_buf)
00470 {
00471     //排他処理をして、メモリを開放する。
00472     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00473     NyLPC_cMutex_lock(&(inst->_mutex));
00474     //ペイロードの位置から、メモリブロックを再生。
00475     NyLPC_iEthernetDevice_releaseTxBuf(inst->_ethif,((struct NyLPC_TEthernetIIHeader*)i_buf)-1);
00476     NyLPC_cMutex_unlock(&(inst->_mutex));
00477     return NULL;
00478 }
00479 
00480 
00481 
00482 
00483 
00484 
00485 
00486 
00487 
00488 /**
00489  * イーサネットフレームを送信します。
00490  * この関数はiptaskで実行される関数からのみ使用てください。
00491  * @i_buf
00492  * イーサネットフレームを格納したメモリです。
00493  * @i_len
00494  * イーサネットペイロードのサイズです。
00495  */
00496 static void sendRawEthFrameNL(void* i_buf,NyLPC_TUInt16 i_len)
00497 {
00498     NyLPC_iEthernetDevice_sendTxEthFrame(
00499         _NyLPC_TcMiMicIpNetIf_inst->_ethif,
00500         ((struct NyLPC_TEthernetIIHeader*)i_buf)-1,
00501         i_len);
00502     return;
00503 }
00504 /**
00505  * ロック状態で使用できるreleaseTxBuf。
00506  * この関数はiptaskで実行される関数からのみ使用してください。
00507  */
00508 static void releaseTxBufNL(void* i_buf)
00509 {
00510     //ペイロードの位置から、メモリブロックを再生。
00511     NyLPC_iEthernetDevice_releaseTxBuf(
00512         _NyLPC_TcMiMicIpNetIf_inst->_ethif,
00513         ((struct NyLPC_TEthernetIIHeader*)i_buf)-1);
00514     return;
00515 }
00516 /**
00517  * マルチキャスとアドレスへ変換する。
00518  */
00519 static void ip2MulticastEmacAddr(const struct NyLPC_TIPv4Addr* i_addr,struct NyLPC_TEthAddr* o_emac)
00520 {
00521     NyLPC_TUInt32 n=NyLPC_htonl(i_addr->v);
00522     o_emac->addr[0]=0x01;
00523     o_emac->addr[1]=0x00;
00524     o_emac->addr[2]=0x5E;
00525     o_emac->addr[3]=((n>>16) & 0x7f);
00526     o_emac->addr[4]=((n>> 8) & 0xff);
00527     o_emac->addr[5]=(n & 0xff);
00528     return;
00529 };
00530 
00531 /**
00532  * ペイロードをIPパケットとしてネットワークへ送出します。
00533  * コール前に、必ずロックしてから呼び出してください。
00534  * @param i_eth_payload
00535  * allocTxBufで確保したメモリを指定してください。
00536  * ペイロードには、TCP/IPパケットを格納します。
00537  */
00538 static NyLPC_TBool sendIPv4Tx(struct TEthPacket* i_eth_buf)
00539 {
00540     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00541     struct NyLPC_TEthAddr emac;
00542     NyLPC_TUInt16 tx_len;
00543     const struct NyLPC_TEthAddr* eth_dest;
00544     //ペイロードのアドレスから、イーサネットフレームバッファのアドレスを復元
00545 
00546     if(NyLPC_TIPv4Addr_isEqual(&(i_eth_buf->data.ipv4.destipaddr),&NyLPC_TIPv4Addr_BROADCAST)) {
00547         //ブロードキャストならそのまま
00548         eth_dest=&NyLPC_TEthAddr_BROADCAST;
00549     }else if(NyLPC_TIPv4Addr_isEqualWithMask(&(i_eth_buf->data.ipv4.destipaddr),&NyLPC_TIPv4Addr_MULTICAST,&NyLPC_TIPv4Addr_MULTICAST_MASK)){
00550         //マルチキャスト
00551         ip2MulticastEmacAddr(&(i_eth_buf->data.ipv4.destipaddr),&emac);
00552         eth_dest=&emac;
00553     }else{
00554         //LocalIP以外ならdefaultRootへ変換
00555         eth_dest=NyLPC_cIPv4Arp_IPv4toEthAddr(
00556             &inst->_arp,
00557             NyLPC_cIPv4Config_isLocalIP(inst->_netinfo.current_config, &(i_eth_buf->data.ipv4.destipaddr))?(i_eth_buf->data.ipv4.destipaddr):(inst->_netinfo.current_config->dr_addr));
00558         //IP->MAC変換をテスト。
00559         if(eth_dest==NULL){
00560             return NyLPC_TBool_FALSE;
00561         }
00562     }
00563     //変換可能なら、イーサネットヘッダを更新して、送信処理へ。
00564     tx_len=NyLPC_TEthernetIIHeader_setIPv4Tx(&(i_eth_buf->header),&(inst->_netinfo.current_config->eth_mac),eth_dest);
00565     NyLPC_iEthernetDevice_sendTxEthFrame(inst->_ethif,i_eth_buf,tx_len);
00566     return NyLPC_TBool_TRUE;
00567 }
00568 
00569 static NyLPC_TBool isInitService(void)
00570 {
00571     return _NyLPC_TcMiMicIpNetIf_inst!=NULL;
00572 }
00573 
00574 //--------------------------------------------------------------------------------
00575 //
00576 //  NetIF Interface
00577 //
00578 //--------------------------------------------------------------------------------
00579 
00580 
00581 //--------------------------------------------------------------------------------
00582 // ソケットテーブル
00583 //--------------------------------------------------------------------------------
00584 
00585 #define FLAGS_USED  0x00000001
00586 
00587 struct TTcpTable
00588 {
00589     NyLPC_TUInt32 flags;
00590     NyLPC_TcMiMicIpTcpSocket_t socket;
00591     NyLPC_TUInt8 rxbuf[NyLPC_cMiMicIpNetIf_config_TCPSOCKET_RX_BUFFER_SIZE];
00592 };
00593 struct TUdpTable
00594 {
00595     NyLPC_TUInt32 flags;
00596     NyLPC_TcMiMicIpUdpSocket_t socket;
00597     NyLPC_TUInt8 rxbuf[NyLPC_cMiMicIpNetIf_config_UDPSOCKET_RX_BUFFER_SIZE];
00598 };
00599 struct TUdpNBTable
00600 {
00601     NyLPC_TUInt32 flags;
00602     NyLPC_TcMiMicIpUdpSocket_t socket;
00603 };
00604 struct TTcpListenerTable
00605 {
00606     NyLPC_TUInt32 flags;
00607     NyLPC_TcMiMicIpTcpListener_t listener;
00608 };
00609 
00610 
00611 
00612 static struct TTcpTable tcp_socket_table[NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX];
00613 static struct TUdpTable udp_socket_table[NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX];
00614 static struct TUdpNBTable udp_socket_nb_table[NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX];
00615 static struct TTcpListenerTable tcp_listener_table[NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX];
00616 
00617 NyLPC_TcMiMicIpTcpListener_t* NyLPC_cMiMicIpNetIf_getListenerByPeerPort(NyLPC_TUInt16 i_port)
00618 {
00619     int i;
00620     //一致するポートを検索して、acceptをコールする。
00621     for(i=NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX-1;i>=0;i--){
00622         if((tcp_listener_table[i].flags&FLAGS_USED)==0){
00623             continue;
00624         }
00625         if(tcp_listener_table[i].listener._port!=i_port){
00626             continue;
00627         }
00628         return &tcp_listener_table[i].listener;
00629     }
00630     return NULL;
00631 }
00632 
00633 /**
00634  * 指定番号のTCPポートが未使用かを返す。
00635  * @return
00636  * i_lport番のポートが未使用であればTRUE
00637  */
00638 NyLPC_TBool NyLPC_cMiMicIpNetIf_isClosedTcpPort(NyLPC_TUInt16 i_lport)
00639 {
00640     int i;
00641     //未使用のTCPソケット?
00642     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00643         if( ((tcp_socket_table[i].flags&FLAGS_USED)!=0) &&
00644             (NyLPC_cMiMicIpTcpSocket_getLocalPort(&tcp_socket_table[i].socket)==i_lport)&&
00645             (!NyLPC_cMiMicIpTcpSocket_isClosed(&tcp_socket_table[i].socket))){
00646             //ポート使用中
00647             return NyLPC_TBool_FALSE;
00648         }
00649     }
00650     for(i=NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX-1;i>=0;i--){
00651         if( ((tcp_listener_table[i].flags&FLAGS_USED)!=0) &&
00652             (NyLPC_cMiMicIpTcpListener_getLocalPort(&tcp_listener_table[i].listener)==i_lport)){
00653             //ポート使用中
00654             return NyLPC_TBool_FALSE;
00655         }
00656     }
00657     return NyLPC_TBool_TRUE;
00658 }
00659 
00660 /**
00661  * 条件に一致する、アクティブなTCPソケットオブジェクトを取得します。
00662  * この関数は、ローカルIPが一致していると仮定して検索をします。
00663  * @param i_rip
00664  * リモートIPアドレスを指定します。
00665  */
00666 NyLPC_TcMiMicIpTcpSocket_t* NyLPC_cMiMicIpNetIf_getMatchTcpSocket(
00667     NyLPC_TUInt16 i_lport,struct NyLPC_TIPv4Addr i_rip,NyLPC_TUInt16 i_rport)
00668 {
00669     NyLPC_TcMiMicIpTcpSocket_t* tp;
00670     int i;
00671     //一致するポートを検索
00672     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00673         if((tcp_socket_table[i].flags&FLAGS_USED)==0){
00674             continue;
00675         }
00676         if(NyLPC_cMiMicIpTcpSocket_isClosed(&tcp_socket_table[i].socket)){
00677             continue;
00678         }
00679         tp=&tcp_socket_table[i].socket;
00680         //パラメータの一致チェック
00681         if(i_lport!=tp->uip_connr.lport || i_rport!= tp->uip_connr.rport || i_rip.v!=tp->uip_connr.ripaddr.v)
00682         {
00683             continue;
00684         }
00685         return tp;
00686     }
00687     return NULL;
00688 }
00689 NyLPC_TcMiMicIpUdpSocket_t* NyLPC_cMiMicIpNetIf_getMatchUdpSocket(
00690     NyLPC_TUInt16 i_lport)
00691 {
00692     int i;
00693     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00694         if((udp_socket_table[i].flags&FLAGS_USED)==0){
00695             continue;
00696         }
00697         if(i_lport!=udp_socket_table[i].socket.uip_udp_conn.lport){
00698             continue;
00699         }
00700         //unicast
00701         return &udp_socket_table[i].socket;
00702     }
00703     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00704         if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
00705             continue;
00706         }
00707         if(i_lport!=udp_socket_nb_table[i].socket.uip_udp_conn.lport){
00708             continue;
00709         }
00710         //unicast
00711         return &udp_socket_nb_table[i].socket;
00712     }
00713     return NULL;
00714 }
00715 NyLPC_TcMiMicIpUdpSocket_t* NyLPC_cMiMicIpNetIf_getMatchMulticastUdpSocket(
00716     const struct NyLPC_TIPv4Addr* i_mcast_ip,
00717     NyLPC_TUInt16 i_lport)
00718 {
00719     int i;
00720     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00721         if((udp_socket_table[i].flags&FLAGS_USED)==0){
00722             continue;
00723         }
00724         if(i_lport!=udp_socket_table[i].socket.uip_udp_conn.lport || (!NyLPC_TIPv4Addr_isEqual(i_mcast_ip,&(udp_socket_table[i].socket.uip_udp_conn.mcastaddr))))
00725         {
00726             continue;
00727         }
00728         return &udp_socket_table[i].socket;
00729     }
00730     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00731         if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
00732             continue;
00733         }
00734         if(i_lport!=udp_socket_nb_table[i].socket.uip_udp_conn.lport || (!NyLPC_TIPv4Addr_isEqual(i_mcast_ip,&(udp_socket_nb_table[i].socket.uip_udp_conn.mcastaddr))))
00735         {
00736             continue;
00737         }
00738         return &udp_socket_nb_table[i].socket;
00739     }
00740     return NULL;
00741 }
00742 
00743 
00744 void NyLPC_cMiMicIpNetIf_callPeriodic(void)
00745 {
00746     int i;
00747     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00748         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
00749             NyLPC_cMiMicIpUdpSocket_periodic(&udp_socket_table[i].socket);
00750         }
00751     }
00752     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00753         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
00754             NyLPC_cMiMicIpUdpSocket_periodic(&udp_socket_nb_table[i].socket);
00755         }
00756     }
00757     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00758         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
00759             NyLPC_cMiMicIpTcpSocket_periodic(&tcp_socket_table[i].socket);
00760         }
00761     }
00762 }
00763 void NyLPC_cMiMicIpNetIf_callSocketStart(
00764     const NyLPC_TcIPv4Config_t* i_cfg)
00765 {
00766     int i;
00767     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00768         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
00769             NyLPC_cMiMicIpUdpSocket_startService(&udp_socket_table[i].socket,i_cfg);
00770         }
00771     }
00772     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00773         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
00774             NyLPC_cMiMicIpUdpSocket_startService(&udp_socket_nb_table[i].socket,i_cfg);
00775         }
00776     }
00777     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00778         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
00779             NyLPC_cMiMicIpTcpSocket_startService(&tcp_socket_table[i].socket,i_cfg);
00780         }
00781     }
00782 }
00783 void NyLPC_cMiMicIpNetIf_callSocketStop(void)
00784 {
00785     int i;
00786     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00787         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
00788             NyLPC_cMiMicIpUdpSocket_stopService(&udp_socket_table[i].socket);
00789         }
00790     }
00791     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00792         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
00793             NyLPC_cMiMicIpUdpSocket_stopService(&udp_socket_nb_table[i].socket);
00794         }
00795     }
00796     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00797         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
00798             NyLPC_cMiMicIpTcpSocket_stopService(&tcp_socket_table[i].socket);
00799         }
00800     }
00801 }
00802 
00803 
00804 
00805 //--------------------------------------------------------------------------------
00806 // インタフェイス関数
00807 
00808 static NyLPC_TiTcpSocket_t* createTcpSocetEx(NyLPC_TSocketType i_socktype)
00809 {
00810     NyLPC_TUInt16 i;
00811     switch(i_socktype){
00812     case NyLPC_TSocketType_TCP_HTTP:
00813     case NyLPC_TSocketType_TCP_NORMAL:
00814         //空きソケットの探索
00815         for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX;i++){
00816             //未使用なソケットを得る
00817             if((tcp_socket_table[i].flags&FLAGS_USED)==0){
00818                 if(!NyLPC_cMiMicIpTcpSocket_initialize(&tcp_socket_table[i].socket,tcp_socket_table[i].rxbuf,NyLPC_cMiMicIpNetIf_config_TCPSOCKET_RX_BUFFER_SIZE)){
00819                     return NULL;
00820                 }
00821                 //ソケットを使用中に
00822                 tcp_socket_table[i].flags|=FLAGS_USED;
00823                 return &(tcp_socket_table[i].socket._super);
00824             }
00825         }
00826         break;
00827     default:
00828         break;
00829     }
00830     return NULL;
00831 }
00832 
00833 static NyLPC_TiUdpSocket_t* createUdpSocetEx(NyLPC_TUInt16 i_port,NyLPC_TSocketType i_socktype)
00834 {
00835     NyLPC_TUInt16 i;
00836     switch(i_socktype){
00837     case NyLPC_TSocketType_UDP_NORMAL:
00838         //空きソケットの探索
00839         for(i=0;i<NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX;i++){
00840             //未使用なソケットを得る
00841             if((udp_socket_table[i].flags&FLAGS_USED)==0){
00842                 if(!NyLPC_cMiMicIpUdpSocket_initialize(&udp_socket_table[i].socket,i_port,udp_socket_table[i].rxbuf,NyLPC_cMiMicIpNetIf_config_UDPSOCKET_RX_BUFFER_SIZE)){
00843                     return NULL;
00844                 }
00845                 udp_socket_table[i].flags|=FLAGS_USED;
00846                 return &(udp_socket_table[i].socket._super);
00847             }
00848         }
00849         break;
00850     case NyLPC_TSocketType_UDP_NOBUF:
00851         //空きソケットの探索
00852         for(i=0;i<NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX;i++){
00853             //未使用なソケットを得る
00854             if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
00855                 if(!NyLPC_cMiMicIpUdpSocket_initialize(&udp_socket_nb_table[i].socket,i_port,NULL,0)){
00856                     return NULL;
00857                 }
00858                 udp_socket_nb_table[i].flags|=FLAGS_USED;
00859                 return &(udp_socket_nb_table[i].socket._super);
00860             }
00861         }
00862         break;
00863     default:
00864         break;
00865     }
00866     return NULL;
00867 }
00868 static NyLPC_TiTcpListener_t* createTcpListener(NyLPC_TUInt16 i_port)
00869 {
00870     NyLPC_TUInt16 i;
00871     //空きソケットの探索
00872     for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX;i++){
00873         //未使用なソケットを得る
00874         if((tcp_listener_table[i].flags&FLAGS_USED)==0){
00875             if(!NyLPC_cMiMicIpTcpListener_initialize(&tcp_listener_table[i].listener,i_port)){
00876                 return NULL;
00877             }
00878             //ソケットを使用中に
00879             tcp_listener_table[i].flags|=FLAGS_USED;
00880             return &(tcp_listener_table[i].listener._super);
00881         }
00882     }
00883     return NULL;
00884 }
00885 
00886 
00887 static const struct NyLPC_TiNetInterface_Interface _interface=
00888 {
00889     createTcpSocetEx,
00890     createUdpSocetEx,
00891     createTcpListener,
00892     NyLPC_cMiMicIpNetIf_start,
00893     NyLPC_cMiMicIpNetIf_stop,
00894     NyLPC_cMiMicIpNetIf_sendArpRequest,
00895     NyLPC_cMiMicIpNetIf_hasArpInfo,
00896     isInitService,//NyLPC_TiNetInterface_isInitService isinitservice;
00897     NyLPC_cMiMicIpNetIf_getInterfaceInfo
00898 };
00899 //--------------------------------------------------------------------------------
00900 // インスタンスのリリース(protected)
00901 
00902 void NyLPC_cMiMicIpNetIf_releaseTcpSocketMemory(const NyLPC_TcMiMicIpTcpSocket_t* i_inst)
00903 {
00904     NyLPC_TUInt16 i;
00905     //空きソケットの探索
00906     for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX;i++){
00907         if((&tcp_socket_table[i].socket)==i_inst){
00908             tcp_socket_table[i].flags&=~FLAGS_USED;
00909             return;
00910         }
00911     }
00912     return;
00913 }
00914 void NyLPC_cMiMicIpNetIf_releaseUdpSocketMemory(const NyLPC_TcMiMicIpUdpSocket_t* i_inst)
00915 {
00916     NyLPC_TUInt16 i;
00917     for(i=0;i<NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX;i++){
00918         if((&udp_socket_table[i].socket)==i_inst){
00919             udp_socket_table[i].flags&=~FLAGS_USED;
00920             return;
00921         }
00922     }
00923     for(i=0;i<NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX;i++){
00924         if((&udp_socket_nb_table[i].socket)==i_inst){
00925             udp_socket_nb_table[i].flags&=~FLAGS_USED;
00926             return;
00927         }
00928     }
00929     return;
00930 }
00931 void NyLPC_cMiMicIpNetIf_releaseTcpListenerMemory(const NyLPC_TcMiMicIpTcpListener_t* i_inst)
00932 {
00933     NyLPC_TUInt16 i;
00934     //空きソケットの探索
00935     for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX;i++){
00936         if((&tcp_listener_table[i].listener)==i_inst){
00937             tcp_listener_table[i].flags&=~FLAGS_USED;
00938             return;
00939         }
00940     }
00941     return;
00942 }
00943 
00944 static NyLPC_TcMiMicIpNetIf_t _netif;
00945 
00946 const struct NyLPC_TiNetInterface_Interface* NyLPC_cMiMicIpNetIf_getNetInterface(void)
00947 {
00948     NyLPC_cMiMicIpNetIf_initialize(&_netif);
00949     return &_interface;
00950 }
00951 
00952 
00953