Jun Furutani / libMiMic

Fork of libMiMic by Ryo Iizuka

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     {
00412         //LocalIP以外ならdefaultRootへ変換
00413         NyLPC_TBool isLocal = NyLPC_cIPv4Config_isLocalIP(inst->_netinfo.current_config, &((struct NyLPC_TIPv4Header*)i_eth_payload)->destipaddr);
00414         NyLPC_cMiMicIpNetIf_sendArpRequest(isLocal ? &((struct NyLPC_TIPv4Header*)i_eth_payload)->destipaddr : &(inst->_netinfo.current_config->dr_addr));
00415     }
00416     return;
00417 }
00418 
00419 
00420 /**
00421  * ARPテーブルに指定したIPがあるかを返します。
00422  */
00423 NyLPC_TBool NyLPC_cMiMicIpNetIf_hasArpInfo(const struct NyLPC_TIPv4Addr* i_addr)
00424 {
00425     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00426     return NyLPC_cIPv4Arp_IPv4toEthAddr(&inst->_arp,*i_addr)!=NULL;
00427 }
00428 
00429 /**
00430  * システム用の送信ペイロードを返します。
00431  * 関数は必ず成功します。
00432  */
00433 void* NyLPC_cMiMicIpNetIf_allocSysTxBuf(void)
00434 {
00435     NyLPC_TUInt16 s;
00436     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00437     struct TEthPacket* ethbuf;
00438     //排他処理をして、メモリを取得する。SYSTEMメモリはEthernetドライバの解放待ちのみなのでまとめてLOCKしておk
00439     NyLPC_cMutex_lock(&(inst->_mutex));
00440     for(;;){
00441         ethbuf=(struct TEthPacket*)NyLPC_iEthernetDevice_allocTxBuf(inst->_ethif,NyLPC_TcEthernetMM_HINT_CTRL_PACKET,&s);
00442         if(ethbuf==NULL){
00443             NyLPC_cThread_yield();
00444             continue;
00445         }
00446         break;
00447     }
00448     NyLPC_cMutex_unlock(&(inst->_mutex));
00449     //イーサネットバッファのアドレスを計算
00450     return &(ethbuf->data);
00451 }
00452 
00453 
00454 
00455 void* NyLPC_cMiMicIpNetIf_allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
00456 {
00457     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00458     struct TEthPacket* ethbuf;
00459     //排他処理をして、メモリを取得する。
00460     NyLPC_cMutex_lock(&(inst->_mutex));
00461     ethbuf=(struct TEthPacket*)NyLPC_iEthernetDevice_allocTxBuf(inst->_ethif,i_hint+sizeof(struct NyLPC_TEthernetIIHeader),o_size);
00462     NyLPC_cMutex_unlock(&(inst->_mutex));
00463     if(ethbuf==NULL){
00464         return NULL;
00465     }
00466     //イーサネットバッファのサイズを計算
00467     *o_size-=sizeof(struct NyLPC_TEthernetIIHeader);
00468     //イーサネットバッファのアドレスを計算
00469     return &(ethbuf->data);
00470 }
00471 
00472 
00473 void* NyLPC_cMiMicIpNetIf_releaseTxBuf(void* i_buf)
00474 {
00475     //排他処理をして、メモリを開放する。
00476     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00477     NyLPC_cMutex_lock(&(inst->_mutex));
00478     //ペイロードの位置から、メモリブロックを再生。
00479     NyLPC_iEthernetDevice_releaseTxBuf(inst->_ethif,((struct NyLPC_TEthernetIIHeader*)i_buf)-1);
00480     NyLPC_cMutex_unlock(&(inst->_mutex));
00481     return NULL;
00482 }
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 /**
00493  * イーサネットフレームを送信します。
00494  * この関数はiptaskで実行される関数からのみ使用てください。
00495  * @i_buf
00496  * イーサネットフレームを格納したメモリです。
00497  * @i_len
00498  * イーサネットペイロードのサイズです。
00499  */
00500 static void sendRawEthFrameNL(void* i_buf,NyLPC_TUInt16 i_len)
00501 {
00502     NyLPC_iEthernetDevice_sendTxEthFrame(
00503         _NyLPC_TcMiMicIpNetIf_inst->_ethif,
00504         ((struct NyLPC_TEthernetIIHeader*)i_buf)-1,
00505         i_len);
00506     return;
00507 }
00508 /**
00509  * ロック状態で使用できるreleaseTxBuf。
00510  * この関数はiptaskで実行される関数からのみ使用してください。
00511  */
00512 static void releaseTxBufNL(void* i_buf)
00513 {
00514     //ペイロードの位置から、メモリブロックを再生。
00515     NyLPC_iEthernetDevice_releaseTxBuf(
00516         _NyLPC_TcMiMicIpNetIf_inst->_ethif,
00517         ((struct NyLPC_TEthernetIIHeader*)i_buf)-1);
00518     return;
00519 }
00520 /**
00521  * マルチキャスとアドレスへ変換する。
00522  */
00523 static void ip2MulticastEmacAddr(const struct NyLPC_TIPv4Addr* i_addr,struct NyLPC_TEthAddr* o_emac)
00524 {
00525     NyLPC_TUInt32 n=NyLPC_htonl(i_addr->v);
00526     o_emac->addr[0]=0x01;
00527     o_emac->addr[1]=0x00;
00528     o_emac->addr[2]=0x5E;
00529     o_emac->addr[3]=((n>>16) & 0x7f);
00530     o_emac->addr[4]=((n>> 8) & 0xff);
00531     o_emac->addr[5]=(n & 0xff);
00532     return;
00533 };
00534 
00535 /**
00536  * ペイロードをIPパケットとしてネットワークへ送出します。
00537  * コール前に、必ずロックしてから呼び出してください。
00538  * @param i_eth_payload
00539  * allocTxBufで確保したメモリを指定してください。
00540  * ペイロードには、TCP/IPパケットを格納します。
00541  */
00542 static NyLPC_TBool sendIPv4Tx(struct TEthPacket* i_eth_buf)
00543 {
00544     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
00545     struct NyLPC_TEthAddr emac;
00546     NyLPC_TUInt16 tx_len;
00547     const struct NyLPC_TEthAddr* eth_dest;
00548     //ペイロードのアドレスから、イーサネットフレームバッファのアドレスを復元
00549 
00550     if(NyLPC_TIPv4Addr_isEqual(&(i_eth_buf->data.ipv4.destipaddr),&NyLPC_TIPv4Addr_BROADCAST)) {
00551         //ブロードキャストならそのまま
00552         eth_dest=&NyLPC_TEthAddr_BROADCAST;
00553     }else if(NyLPC_TIPv4Addr_isEqualWithMask(&(i_eth_buf->data.ipv4.destipaddr),&NyLPC_TIPv4Addr_MULTICAST,&NyLPC_TIPv4Addr_MULTICAST_MASK)){
00554         //マルチキャスト
00555         ip2MulticastEmacAddr(&(i_eth_buf->data.ipv4.destipaddr),&emac);
00556         eth_dest=&emac;
00557     }else{
00558         //LocalIP以外ならdefaultRootへ変換
00559         eth_dest=NyLPC_cIPv4Arp_IPv4toEthAddr(
00560             &inst->_arp,
00561             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));
00562         //IP->MAC変換をテスト。
00563         if(eth_dest==NULL){
00564             return NyLPC_TBool_FALSE;
00565         }
00566     }
00567     //変換可能なら、イーサネットヘッダを更新して、送信処理へ。
00568     tx_len=NyLPC_TEthernetIIHeader_setIPv4Tx(&(i_eth_buf->header),&(inst->_netinfo.current_config->eth_mac),eth_dest);
00569     NyLPC_iEthernetDevice_sendTxEthFrame(inst->_ethif,i_eth_buf,tx_len);
00570     return NyLPC_TBool_TRUE;
00571 }
00572 
00573 static NyLPC_TBool isInitService(void)
00574 {
00575     return _NyLPC_TcMiMicIpNetIf_inst!=NULL;
00576 }
00577 
00578 //--------------------------------------------------------------------------------
00579 //
00580 //  NetIF Interface
00581 //
00582 //--------------------------------------------------------------------------------
00583 
00584 
00585 //--------------------------------------------------------------------------------
00586 // ソケットテーブル
00587 //--------------------------------------------------------------------------------
00588 
00589 #define FLAGS_USED  0x00000001
00590 
00591 struct TTcpTable
00592 {
00593     NyLPC_TUInt32 flags;
00594     NyLPC_TcMiMicIpTcpSocket_t socket;
00595     NyLPC_TUInt8 rxbuf[NyLPC_cMiMicIpNetIf_config_TCPSOCKET_RX_BUFFER_SIZE];
00596 };
00597 struct TUdpTable
00598 {
00599     NyLPC_TUInt32 flags;
00600     NyLPC_TcMiMicIpUdpSocket_t socket;
00601     NyLPC_TUInt8 rxbuf[NyLPC_cMiMicIpNetIf_config_UDPSOCKET_RX_BUFFER_SIZE];
00602 };
00603 struct TUdpNBTable
00604 {
00605     NyLPC_TUInt32 flags;
00606     NyLPC_TcMiMicIpUdpSocket_t socket;
00607 };
00608 struct TTcpListenerTable
00609 {
00610     NyLPC_TUInt32 flags;
00611     NyLPC_TcMiMicIpTcpListener_t listener;
00612 };
00613 
00614 
00615 
00616 static struct TTcpTable tcp_socket_table[NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX];
00617 static struct TUdpTable udp_socket_table[NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX];
00618 static struct TUdpNBTable udp_socket_nb_table[NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX];
00619 static struct TTcpListenerTable tcp_listener_table[NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX];
00620 
00621 NyLPC_TcMiMicIpTcpListener_t* NyLPC_cMiMicIpNetIf_getListenerByPeerPort(NyLPC_TUInt16 i_port)
00622 {
00623     int i;
00624     //一致するポートを検索して、acceptをコールする。
00625     for(i=NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX-1;i>=0;i--){
00626         if((tcp_listener_table[i].flags&FLAGS_USED)==0){
00627             continue;
00628         }
00629         if(tcp_listener_table[i].listener._port!=i_port){
00630             continue;
00631         }
00632         return &tcp_listener_table[i].listener;
00633     }
00634     return NULL;
00635 }
00636 
00637 /**
00638  * 指定番号のTCPポートが未使用かを返す。
00639  * @return
00640  * i_lport番のポートが未使用であればTRUE
00641  */
00642 NyLPC_TBool NyLPC_cMiMicIpNetIf_isClosedTcpPort(NyLPC_TUInt16 i_lport)
00643 {
00644     int i;
00645     //未使用のTCPソケット?
00646     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00647         if( ((tcp_socket_table[i].flags&FLAGS_USED)!=0) &&
00648             (NyLPC_cMiMicIpTcpSocket_getLocalPort(&tcp_socket_table[i].socket)==i_lport)&&
00649             (!NyLPC_cMiMicIpTcpSocket_isClosed(&tcp_socket_table[i].socket))){
00650             //ポート使用中
00651             return NyLPC_TBool_FALSE;
00652         }
00653     }
00654     for(i=NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX-1;i>=0;i--){
00655         if( ((tcp_listener_table[i].flags&FLAGS_USED)!=0) &&
00656             (NyLPC_cMiMicIpTcpListener_getLocalPort(&tcp_listener_table[i].listener)==i_lport)){
00657             //ポート使用中
00658             return NyLPC_TBool_FALSE;
00659         }
00660     }
00661     return NyLPC_TBool_TRUE;
00662 }
00663 
00664 /**
00665  * 条件に一致する、アクティブなTCPソケットオブジェクトを取得します。
00666  * この関数は、ローカルIPが一致していると仮定して検索をします。
00667  * @param i_rip
00668  * リモートIPアドレスを指定します。
00669  */
00670 NyLPC_TcMiMicIpTcpSocket_t* NyLPC_cMiMicIpNetIf_getMatchTcpSocket(
00671     NyLPC_TUInt16 i_lport,struct NyLPC_TIPv4Addr i_rip,NyLPC_TUInt16 i_rport)
00672 {
00673     NyLPC_TcMiMicIpTcpSocket_t* tp;
00674     int i;
00675     //一致するポートを検索
00676     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00677         if((tcp_socket_table[i].flags&FLAGS_USED)==0){
00678             continue;
00679         }
00680         if(NyLPC_cMiMicIpTcpSocket_isClosed(&tcp_socket_table[i].socket)){
00681             continue;
00682         }
00683         tp=&tcp_socket_table[i].socket;
00684         //パラメータの一致チェック
00685         if(i_lport!=tp->uip_connr.lport || i_rport!= tp->uip_connr.rport || i_rip.v!=tp->uip_connr.ripaddr.v)
00686         {
00687             continue;
00688         }
00689         return tp;
00690     }
00691     return NULL;
00692 }
00693 NyLPC_TcMiMicIpUdpSocket_t* NyLPC_cMiMicIpNetIf_getMatchUdpSocket(
00694     NyLPC_TUInt16 i_lport)
00695 {
00696     int i;
00697     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00698         if((udp_socket_table[i].flags&FLAGS_USED)==0){
00699             continue;
00700         }
00701         if(i_lport!=udp_socket_table[i].socket.uip_udp_conn.lport){
00702             continue;
00703         }
00704         //unicast
00705         return &udp_socket_table[i].socket;
00706     }
00707     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00708         if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
00709             continue;
00710         }
00711         if(i_lport!=udp_socket_nb_table[i].socket.uip_udp_conn.lport){
00712             continue;
00713         }
00714         //unicast
00715         return &udp_socket_nb_table[i].socket;
00716     }
00717     return NULL;
00718 }
00719 NyLPC_TcMiMicIpUdpSocket_t* NyLPC_cMiMicIpNetIf_getMatchMulticastUdpSocket(
00720     const struct NyLPC_TIPv4Addr* i_mcast_ip,
00721     NyLPC_TUInt16 i_lport)
00722 {
00723     int i;
00724     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00725         if((udp_socket_table[i].flags&FLAGS_USED)==0){
00726             continue;
00727         }
00728         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))))
00729         {
00730             continue;
00731         }
00732         return &udp_socket_table[i].socket;
00733     }
00734     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00735         if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
00736             continue;
00737         }
00738         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))))
00739         {
00740             continue;
00741         }
00742         return &udp_socket_nb_table[i].socket;
00743     }
00744     return NULL;
00745 }
00746 
00747 
00748 void NyLPC_cMiMicIpNetIf_callPeriodic(void)
00749 {
00750     int i;
00751     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00752         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
00753             NyLPC_cMiMicIpUdpSocket_periodic(&udp_socket_table[i].socket);
00754         }
00755     }
00756     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00757         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
00758             NyLPC_cMiMicIpUdpSocket_periodic(&udp_socket_nb_table[i].socket);
00759         }
00760     }
00761     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00762         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
00763             NyLPC_cMiMicIpTcpSocket_periodic(&tcp_socket_table[i].socket);
00764         }
00765     }
00766 }
00767 void NyLPC_cMiMicIpNetIf_callSocketStart(
00768     const NyLPC_TcIPv4Config_t* i_cfg)
00769 {
00770     int i;
00771     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00772         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
00773             NyLPC_cMiMicIpUdpSocket_startService(&udp_socket_table[i].socket,i_cfg);
00774         }
00775     }
00776     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00777         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
00778             NyLPC_cMiMicIpUdpSocket_startService(&udp_socket_nb_table[i].socket,i_cfg);
00779         }
00780     }
00781     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00782         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
00783             NyLPC_cMiMicIpTcpSocket_startService(&tcp_socket_table[i].socket,i_cfg);
00784         }
00785     }
00786 }
00787 void NyLPC_cMiMicIpNetIf_callSocketStop(void)
00788 {
00789     int i;
00790     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
00791         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
00792             NyLPC_cMiMicIpUdpSocket_stopService(&udp_socket_table[i].socket);
00793         }
00794     }
00795     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
00796         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
00797             NyLPC_cMiMicIpUdpSocket_stopService(&udp_socket_nb_table[i].socket);
00798         }
00799     }
00800     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
00801         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
00802             NyLPC_cMiMicIpTcpSocket_stopService(&tcp_socket_table[i].socket);
00803         }
00804     }
00805 }
00806 
00807 
00808 
00809 //--------------------------------------------------------------------------------
00810 // インタフェイス関数
00811 
00812 static NyLPC_TiTcpSocket_t* createTcpSocetEx(NyLPC_TSocketType i_socktype)
00813 {
00814     NyLPC_TUInt16 i;
00815     switch(i_socktype){
00816     case NyLPC_TSocketType_TCP_HTTP:
00817     case NyLPC_TSocketType_TCP_NORMAL:
00818         //空きソケットの探索
00819         for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX;i++){
00820             //未使用なソケットを得る
00821             if((tcp_socket_table[i].flags&FLAGS_USED)==0){
00822                 if(!NyLPC_cMiMicIpTcpSocket_initialize(&tcp_socket_table[i].socket,tcp_socket_table[i].rxbuf,NyLPC_cMiMicIpNetIf_config_TCPSOCKET_RX_BUFFER_SIZE)){
00823                     return NULL;
00824                 }
00825                 //ソケットを使用中に
00826                 tcp_socket_table[i].flags|=FLAGS_USED;
00827                 return &(tcp_socket_table[i].socket._super);
00828             }
00829         }
00830         break;
00831     default:
00832         break;
00833     }
00834     return NULL;
00835 }
00836 
00837 static NyLPC_TiUdpSocket_t* createUdpSocetEx(NyLPC_TUInt16 i_port,NyLPC_TSocketType i_socktype)
00838 {
00839     NyLPC_TUInt16 i;
00840     switch(i_socktype){
00841     case NyLPC_TSocketType_UDP_NORMAL:
00842         //空きソケットの探索
00843         for(i=0;i<NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX;i++){
00844             //未使用なソケットを得る
00845             if((udp_socket_table[i].flags&FLAGS_USED)==0){
00846                 if(!NyLPC_cMiMicIpUdpSocket_initialize(&udp_socket_table[i].socket,i_port,udp_socket_table[i].rxbuf,NyLPC_cMiMicIpNetIf_config_UDPSOCKET_RX_BUFFER_SIZE)){
00847                     return NULL;
00848                 }
00849                 udp_socket_table[i].flags|=FLAGS_USED;
00850                 return &(udp_socket_table[i].socket._super);
00851             }
00852         }
00853         break;
00854     case NyLPC_TSocketType_UDP_NOBUF:
00855         //空きソケットの探索
00856         for(i=0;i<NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX;i++){
00857             //未使用なソケットを得る
00858             if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
00859                 if(!NyLPC_cMiMicIpUdpSocket_initialize(&udp_socket_nb_table[i].socket,i_port,NULL,0)){
00860                     return NULL;
00861                 }
00862                 udp_socket_nb_table[i].flags|=FLAGS_USED;
00863                 return &(udp_socket_nb_table[i].socket._super);
00864             }
00865         }
00866         break;
00867     default:
00868         break;
00869     }
00870     return NULL;
00871 }
00872 static NyLPC_TiTcpListener_t* createTcpListener(NyLPC_TUInt16 i_port)
00873 {
00874     NyLPC_TUInt16 i;
00875     //空きソケットの探索
00876     for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX;i++){
00877         //未使用なソケットを得る
00878         if((tcp_listener_table[i].flags&FLAGS_USED)==0){
00879             if(!NyLPC_cMiMicIpTcpListener_initialize(&tcp_listener_table[i].listener,i_port)){
00880                 return NULL;
00881             }
00882             //ソケットを使用中に
00883             tcp_listener_table[i].flags|=FLAGS_USED;
00884             return &(tcp_listener_table[i].listener._super);
00885         }
00886     }
00887     return NULL;
00888 }
00889 
00890 
00891 static const struct NyLPC_TiNetInterface_Interface _interface=
00892 {
00893     createTcpSocetEx,
00894     createUdpSocetEx,
00895     createTcpListener,
00896     NyLPC_cMiMicIpNetIf_start,
00897     NyLPC_cMiMicIpNetIf_stop,
00898     NyLPC_cMiMicIpNetIf_sendArpRequest,
00899     NyLPC_cMiMicIpNetIf_hasArpInfo,
00900     isInitService,//NyLPC_TiNetInterface_isInitService isinitservice;
00901     NyLPC_cMiMicIpNetIf_getInterfaceInfo
00902 };
00903 //--------------------------------------------------------------------------------
00904 // インスタンスのリリース(protected)
00905 
00906 void NyLPC_cMiMicIpNetIf_releaseTcpSocketMemory(const NyLPC_TcMiMicIpTcpSocket_t* i_inst)
00907 {
00908     NyLPC_TUInt16 i;
00909     //空きソケットの探索
00910     for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX;i++){
00911         if((&tcp_socket_table[i].socket)==i_inst){
00912             tcp_socket_table[i].flags&=~FLAGS_USED;
00913             return;
00914         }
00915     }
00916     return;
00917 }
00918 void NyLPC_cMiMicIpNetIf_releaseUdpSocketMemory(const NyLPC_TcMiMicIpUdpSocket_t* i_inst)
00919 {
00920     NyLPC_TUInt16 i;
00921     for(i=0;i<NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX;i++){
00922         if((&udp_socket_table[i].socket)==i_inst){
00923             udp_socket_table[i].flags&=~FLAGS_USED;
00924             return;
00925         }
00926     }
00927     for(i=0;i<NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX;i++){
00928         if((&udp_socket_nb_table[i].socket)==i_inst){
00929             udp_socket_nb_table[i].flags&=~FLAGS_USED;
00930             return;
00931         }
00932     }
00933     return;
00934 }
00935 void NyLPC_cMiMicIpNetIf_releaseTcpListenerMemory(const NyLPC_TcMiMicIpTcpListener_t* i_inst)
00936 {
00937     NyLPC_TUInt16 i;
00938     //空きソケットの探索
00939     for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX;i++){
00940         if((&tcp_listener_table[i].listener)==i_inst){
00941             tcp_listener_table[i].flags&=~FLAGS_USED;
00942             return;
00943         }
00944     }
00945     return;
00946 }
00947 
00948 static NyLPC_TcMiMicIpNetIf_t _netif;
00949 
00950 const struct NyLPC_TiNetInterface_Interface* NyLPC_cMiMicIpNetIf_getNetInterface(void)
00951 {
00952     NyLPC_cMiMicIpNetIf_initialize(&_netif);
00953     return &_interface;
00954 }
00955 
00956 
00957