OSDN Git Service

update libMiMic
[mimic/MiMicSDK.git] / lib / src / netif / mimicip / NyLPC_cMiMicIpNetIf.c
1 /*********************************************************************************
2  * PROJECT: MiMic
3  * --------------------------------------------------------------------------------
4  *
5  * This file is part of MiMic
6  * Copyright (C)2011 Ryo Iizuka
7  *
8  * MiMic is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published
10  * by the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  * For further information please contact.
22  *  http://nyatla.jp/
23  *  <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
24  *
25  *
26  * Parts of this file were leveraged from uIP:
27  *
28  * Copyright (c) 2001-2003, Adam Dunkels.
29  * All rights reserved.
30  *
31  * Redistribution and use in source and binary forms, with or without
32  * modification, are permitted provided that the following conditions
33  * are met:
34  * 1. Redistributions of source code must retain the above copyright
35  *    notice, this list of conditions and the following disclaimer.
36  * 2. Redistributions in binary form must reproduce the above copyright
37  *    notice, this list of conditions and the following disclaimer in the
38  *    documentation and/or other materials provided with the distribution.
39  * 3. The name of the author may not be used to endorse or promote
40  *    products derived from this software without specific prior
41  *    written permission.
42  *
43  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
44  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
47  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
49  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
50  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
52  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
53  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54  */
55 //#include "NyLPC_cIPv4IComp_protected.h"
56 //#include "NyLPC_cTcpListener_protected.h"
57 #include "NyLPC_cMiMicIpNetIf_protected.h"
58 #include "NyLPC_stdlib.h"
59 #include "../NyLPC_NetIf_ip_types.h"
60 #include "NyLPC_cIPv4IComp_protected.h"
61 #include "NyLPC_cMiMicIpTcpSocket_protected.h"
62 #include "NyLPC_cMiMicIpUdpSocket_protected.h"
63 #include "NyLPC_cMiMicIpTcpListener_protected.h"
64
65
66
67
68
69 /****************************************************
70  * UipServiceに関する宣言:その他
71  ***************************************************/
72 /**
73  * イーサネットフレームの読み出し構造体
74  */
75 struct TEthPacket
76 {
77     struct NyLPC_TEthernetIIHeader header;
78     union{
79         struct NyLPC_TArpHeader arp;
80         struct NyLPC_TIPv4Header ipv4;
81     }data;
82 }PACK_STRUCT_END;
83
84
85
86 /**
87  * サービスインスタンスのポインタ。サービスが稼働中はインスタンスのポインタが有効です。
88  */
89 NyLPC_TcMiMicIpNetIf_t* _NyLPC_TcMiMicIpNetIf_inst=NULL;
90
91
92
93 /**
94  * uipタスク
95  */
96 static int uipTask(void *pvParameters);
97
98 /** イーサネットドライバからのハンドラ*/
99 static void ethernet_handler(void* i_param,NyLPC_TiEthernetDevice_EVENT i_type);
100
101 //--------------------------------------------------------------
102
103
104 static NyLPC_TBool sendIPv4Tx(struct TEthPacket* i_eth_buf);
105
106 //static void sendArpReqest(const struct TEthPacket* i_eth_packet);
107 static void sendRawEthFrameNL(void* i_buf,NyLPC_TUInt16 i_len);
108 static void releaseTxBufNL(void* i_buf);
109
110 /**メッセージなし*/
111 #define TTaskMessage_MSG_NULL    0x0000
112 /**uipコアタスクに、開始要求する*/
113 #define TTaskMessage_MSG_RUN     0x0001
114 /**uipコアタスクに、停止要求する*/
115 #define TTaskMessage_MSG_STOP    0x0002
116
117
118 static NyLPC_TcThread_t th;
119
120 NyLPC_TBool NyLPC_cMiMicIpNetIf_initialize(NyLPC_TcMiMicIpNetIf_t* i_inst)
121 {
122     //サービスは停止している事。 - Service must be uninitialized.
123     NyLPC_Assert(!NyLPC_cMiMicIpNetIf_isInitService());
124     //IP処理部分の初期化
125     NyLPC_cIPv4_initialize(&(i_inst->_tcpv4));
126     //EMAC割込セマフォ
127     NyLPC_cSemaphore_initialize(&i_inst->_emac_semapho);
128
129     i_inst->_status=0x00;
130     NyLPC_cStopwatch_initialize(&(i_inst->_arp_sw));
131     NyLPC_cStopwatch_initialize(&(i_inst->_periodic_sw));
132     NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(i_inst->_mutex)));
133
134     _NyLPC_TcMiMicIpNetIf_inst=i_inst;
135     //タスク起動
136     NyLPC_cThread_initialize(&th,NyLPC_cMiMicIpNetIf_config_STACK_SIZE,NyLPC_TcThread_PRIORITY_SERVICE);
137     NyLPC_cThread_start(&th,uipTask,NULL);
138     return NyLPC_TBool_TRUE;
139 }
140
141
142
143
144
145
146
147 /**
148  * UIP処理を開始します。
149  * この関数はリエントラントではありません。複数のタスクから共有するときには、排他ロックを掛けてください。
150  * @param i_ref_config
151  * このコンフィギュレーションは、stopを実行するまでの間、インスタンスから参照します。外部で保持してください。
152  */
153 void NyLPC_cMiMicIpNetIf_start(const NyLPC_TcIPv4Config_t* i_ref_config)
154 {
155         NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
156     NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService());
157     if(!NyLPC_cMiMicIpNetIf_isRun())
158     {
159         //はじめて起動するときに1度だけデバイス取得(タスクスイッチが動いてないと動かないからここで。)
160         if(inst->_ethif==NULL){
161             inst->_ethif=getEthernetDevicePnP();
162         }
163         //コンフィグレーションセット
164         inst->_netinfo.current_config=i_ref_config;
165         //開始要求セット
166         NyLPC_TUInt16_setBit(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_START);
167         //Order実行待ち
168         while(NyLPC_TUInt16_isBitOn(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_START)){
169             NyLPC_cThread_sleep(10);
170         }
171         //デバイス情報の追記
172         inst->_netinfo.device_name=NyLPC_iEthernetDevice_getDevicName(inst->_ethif);
173     }
174     return;
175 }
176 /**
177  * UIP処理を停止します。
178  * この関数はリエントラントではありません。複数のタスクから共有するときには、排他ロックを掛けてください。
179  * いまのところ、ストップシーケンスの実装は良くありません。
180  * 再設計が必要。
181  */
182 void NyLPC_cMiMicIpNetIf_stop(void)
183 {
184         NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
185     NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService());
186     if(NyLPC_cMiMicIpNetIf_isRun())
187     {
188         NyLPC_TUInt16_setBit(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_STOP);
189         //Order実行待ち
190         while(NyLPC_TUInt16_isBitOn(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_STOP)){
191             NyLPC_cThread_sleep(10);
192         }
193     }
194     return;
195 }
196
197 static const struct NyLPC_TNetInterfaceInfo* NyLPC_cMiMicIpNetIf_getInterfaceInfo(void)
198 {
199         NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
200     return &inst->_netinfo;
201 }
202
203 /**********************************************************************
204  *
205  * </HWコールバックに関わる宣言>
206  *
207  *********************************************************************/
208
209
210 //PERIODIC rate
211 #define PERIODIC_TIMER (1*200)
212 #define ARP_TIMER (60*1000*10)
213
214
215
216 /**
217  * 操作キューを確認して、タスクのステータスをアップデートします。
218  * 高速化のため、Proc-Callerを使用していません。複雑なタスク操作をするときには、書き換えてください。
219  * @return
220  * UIPタスクの実行状態
221  */
222 static NyLPC_TBool updateTaskStatus()
223 {
224         NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
225     if(NyLPC_cMiMicIpNetIf_isRun()){
226         //開始状態
227         if(NyLPC_TUInt16_isBitOn(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_STOP))
228         {
229             //停止操作
230             NyLPC_iEthernetDevice_stop(inst->_ethif);
231             NyLPC_cIPv4_stop(&(inst->_tcpv4));
232             NyLPC_cIPv4IComp_finalize(&(inst->_icomp));
233             NyLPC_cIPv4Arp_finalize(&(inst->_arp));
234 //            inst->_ref_config=NULL;
235             NyLPC_TUInt16_unsetBit(inst->_status,NyLPC_TcMiMicIpNetIf_STATUSBIT_IS_RUNNING);
236             NyLPC_TUInt16_unsetBit(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_STOP);
237             return NyLPC_TBool_FALSE;
238         }
239         return NyLPC_TBool_TRUE;
240     }else{
241         //停止状態
242         if(NyLPC_TUInt16_isBitOn(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_START))
243         {
244             //TCP,ICOMPの初期化
245             NyLPC_cIPv4_start(&(inst->_tcpv4),inst->_netinfo.current_config);
246             NyLPC_cIPv4IComp_initialize(&(inst->_icomp),inst->_netinfo.current_config);
247             //uip_arp_init(msg->start.ref_config);
248             NyLPC_cIPv4Arp_initialize(&(inst->_arp),inst->_netinfo.current_config);
249             NyLPC_cStopwatch_startExpire(&(inst->_arp_sw),1);//1度ARPを起動するため。
250             NyLPC_cStopwatch_startExpire(&(inst->_periodic_sw),PERIODIC_TIMER);
251             //EtherNETデバイス初期化
252             while(!NyLPC_iEthernetDevice_start(inst->_ethif,&(inst->_netinfo.current_config->eth_mac),ethernet_handler,inst));
253             NyLPC_TUInt16_setBit(inst->_status,NyLPC_TcMiMicIpNetIf_STATUSBIT_IS_RUNNING);
254             NyLPC_TUInt16_unsetBit(inst->_status,NyLPC_TcMiMicIpNetIf_ORDER_START);
255             return NyLPC_TBool_TRUE;
256         }
257         return NyLPC_TBool_FALSE;
258     }
259 }
260
261 /**
262  * uipタスクのメインループ
263  */
264 static int uipTask(void *pvParameters)
265 {
266     NyLPC_TUInt16 rx_len,tx_len;
267     struct TEthPacket* ethbuf;
268     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
269     void* r;
270     (void)pvParameters;
271     for( ;; )
272     {
273         //タスク状態の更新
274         if(!updateTaskStatus())
275         {
276             //RUNステータス以外の時は、ここで終了する。
277             NyLPC_cThread_sleep(50);
278             continue;
279         }
280         //イーサネットフレームの取得
281         //Ethernet Device Lock(ARPを含む)
282         NyLPC_cMutex_lock(&(inst->_mutex));
283         ethbuf= (struct TEthPacket*)NyLPC_iEthernetDevice_getRxEthFrame(inst->_ethif,&rx_len);
284         tx_len=0;
285         while(ethbuf != NULL){
286             if(rx_len>0)
287             {
288                 //ペイロードサイズを計算
289                 rx_len-=sizeof(struct NyLPC_TEthernetIIHeader);
290                 switch(ethbuf->header.type)
291                 {
292                 case NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_IP):
293                     //ARPテーブルの更新
294                     //uip_arp_ipin(&(ethbuf->header),ethbuf->data.ipv4.srcipaddr);
295                     NyLPC_cIPv4Arp_incomingIp(&inst->_arp,&(ethbuf->header),ethbuf->data.ipv4.srcipaddr);
296                     //Ethernet Device UnLock(NyLPC_cIPv4_rxがallocをコールする可能性があるので一時的にロック解除)
297                     NyLPC_cMutex_unlock(&(inst->_mutex));
298                     //IPパケットの処理
299                     r=NyLPC_cIPv4_rx(&(inst->_tcpv4),&(ethbuf->data.ipv4),rx_len);
300                     if(r!=NULL){
301                         //IPパケットとして送信
302                         NyLPC_cMiMicIpNetIf_sendIPv4Tx(r);
303                     }
304                     //ロックの復帰
305                     NyLPC_cMutex_lock(&(inst->_mutex));
306                     if(r!=NULL){
307                         releaseTxBufNL(r);
308                     }
309                     break;
310                 case NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_ARP):
311                     //Ethernet Device UnLock(NyLPC_cIPv4_rxがallocをコールする可能性があるので一時的にロック解除)
312                     NyLPC_cMutex_unlock(&(inst->_mutex));
313                     r=NyLPC_cIPv4Arp_rx(&inst->_arp,&(ethbuf->data.arp),rx_len,&tx_len);
314                     NyLPC_cMutex_lock(&(inst->_mutex));
315                     if(r!=NULL){
316                         sendRawEthFrameNL(r,tx_len);
317                         releaseTxBufNL(r);
318                     }
319                     break;
320                 case NyLPC_HTONS(NyLPC_TEthernetIIHeader_TYPE_IPV6):
321                     //uip_process_ipv6();
322                     break;
323                 default:
324                     break;
325                 }
326             }
327             //受信キューを進行。
328             NyLPC_iEthernetDevice_nextRxEthFrame(inst->_ethif);
329             //受信処理
330             ethbuf= (struct TEthPacket*)NyLPC_iEthernetDevice_getRxEthFrame(inst->_ethif,&rx_len);
331         }
332         //データが無い。
333         if(NyLPC_cStopwatch_isExpired(&(inst->_arp_sw))){
334             //uip_arp_timer();
335             NyLPC_cIPv4Arp_periodic(&inst->_arp);
336             NyLPC_cStopwatch_startExpire(&(inst->_arp_sw),ARP_TIMER);
337         }
338         if(NyLPC_cStopwatch_isExpired(&(inst->_periodic_sw))){
339             NyLPC_cMutex_unlock(&(inst->_mutex));
340             NyLPC_cIPv4_periodec(&(inst->_tcpv4));
341             NyLPC_cMutex_lock(&(inst->_mutex));
342             NyLPC_cStopwatch_startExpire(&(inst->_periodic_sw),PERIODIC_TIMER);
343         }
344         //リソースロックの解除
345         NyLPC_cMutex_unlock(&(inst->_mutex));
346         //割込によるセマフォの解除か、タイムアウトで再開する。(タイムアウト値は周期関数の実行レート以下にすること。)
347         NyLPC_cSemaphore_take(&(_NyLPC_TcMiMicIpNetIf_inst->_emac_semapho),PERIODIC_TIMER);
348     }
349     return 0;
350 }
351
352
353 /**
354  * イーサネットドライバからのハンドラ
355  */
356 static void ethernet_handler(void* i_param,NyLPC_TiEthernetDevice_EVENT i_type)
357 {
358     switch(i_type){
359     case NyLPC_TiEthernetDevice_EVENT_ON_RX:
360         //受信系のセマフォブロックの解除
361         NyLPC_cSemaphore_giveFromISR(&(((NyLPC_TcMiMicIpNetIf_t*)i_param)->_emac_semapho));
362         break;
363     default:
364         break;
365     }
366 }
367
368 /**
369  * IPv4パケットのpeerIPを問い合わせるARPパケットを送信します。
370  * allocを中でコールするから要UNLOCK状態
371  */
372 void NyLPC_cMiMicIpNetIf_sendArpRequest(const struct NyLPC_TIPv4Addr* i_addr)
373 {
374         NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
375     NyLPC_TUInt16 tx_len;
376     struct TEthPacket* ethbuf;
377     //システムTXメモリを得てイーサフレームのポインタを復元
378     ethbuf=(struct TEthPacket*)(((struct NyLPC_TEthernetIIHeader*)NyLPC_cMiMicIpNetIf_allocSysTxBuf()-1));
379     //ARPパケットを作る。
380     NyLPC_TArpHeader_setArpRequest(&(ethbuf->data.arp),inst->_netinfo.current_config->ip_addr,&(inst->_netinfo.current_config->eth_mac),i_addr);
381     tx_len=NyLPC_TEthernetIIHeader_setArpTx(&(ethbuf->header),&(inst->_netinfo.current_config->eth_mac));
382     //送信
383     NyLPC_cMutex_lock(&(inst->_mutex));
384     NyLPC_iEthernetDevice_sendTxEthFrame(inst->_ethif,ethbuf,tx_len);
385     NyLPC_iEthernetDevice_releaseTxBuf(inst->_ethif,ethbuf);//NyLPC_cMiMicIpNetIf_releaseTxBufの代用だから元のイーサフレームメモリの値で開放
386     NyLPC_cMutex_unlock(&(inst->_mutex));
387 }
388
389
390
391
392 /**
393  * allocTxBufで取得したペイロードメモリを"IPパケットとして"送信します。
394  * @param i_eth_payload
395  * [NyLPC_TEthernetIIHeader][payload]メモリの、[payload]のアドレスを指定します。
396  * 通常は、NyLPC_cUipService_allocTxBufの返却したメモリを指定します。
397  */
398
399 void NyLPC_cMiMicIpNetIf_sendIPv4Tx(void* i_eth_payload)
400 {
401         NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
402     void* p=((struct NyLPC_TEthernetIIHeader*)i_eth_payload)-1;
403     NyLPC_cMutex_lock(&(inst->_mutex));
404     //IPパケットの送信を試行
405     if(sendIPv4Tx((struct TEthPacket*)p)){
406         NyLPC_cMutex_unlock(&(inst->_mutex));
407         return;
408     }
409     NyLPC_cMutex_unlock(&(inst->_mutex));
410     //ARPリクエストを代わりに送信
411     NyLPC_cMiMicIpNetIf_sendArpRequest(&((struct NyLPC_TIPv4Header*)i_eth_payload)->destipaddr);
412     return;
413 }
414
415
416 /**
417  * ARPテーブルに指定したIPがあるかを返します。
418  */
419 NyLPC_TBool NyLPC_cMiMicIpNetIf_hasArpInfo(const struct NyLPC_TIPv4Addr* i_addr)
420 {
421         NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
422     return NyLPC_cIPv4Arp_IPv4toEthAddr(&inst->_arp,*i_addr)!=NULL;
423 }
424
425 /**
426  * システム用の送信ペイロードを返します。
427  * 関数は必ず成功します。
428  */
429 void* NyLPC_cMiMicIpNetIf_allocSysTxBuf(void)
430 {
431     NyLPC_TUInt16 s;
432     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
433     struct TEthPacket* ethbuf;
434     //排他処理をして、メモリを取得する。SYSTEMメモリはEthernetドライバの解放待ちのみなのでまとめてLOCKしておk
435     NyLPC_cMutex_lock(&(inst->_mutex));
436     for(;;){
437         ethbuf=(struct TEthPacket*)NyLPC_iEthernetDevice_allocTxBuf(inst->_ethif,NyLPC_TcEthernetMM_HINT_CTRL_PACKET,&s);
438         if(ethbuf==NULL){
439             NyLPC_cThread_yield();
440             continue;
441         }
442         break;
443     }
444     NyLPC_cMutex_unlock(&(inst->_mutex));
445     //イーサネットバッファのアドレスを計算
446     return &(ethbuf->data);
447 }
448
449
450
451 void* NyLPC_cMiMicIpNetIf_allocTxBuf(NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_size)
452 {
453     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
454     struct TEthPacket* ethbuf;
455     //排他処理をして、メモリを取得する。
456     NyLPC_cMutex_lock(&(inst->_mutex));
457     ethbuf=(struct TEthPacket*)NyLPC_iEthernetDevice_allocTxBuf(inst->_ethif,i_hint+sizeof(struct NyLPC_TEthernetIIHeader),o_size);
458     NyLPC_cMutex_unlock(&(inst->_mutex));
459     if(ethbuf==NULL){
460         return NULL;
461     }
462     //イーサネットバッファのサイズを計算
463     *o_size-=sizeof(struct NyLPC_TEthernetIIHeader);
464     //イーサネットバッファのアドレスを計算
465     return &(ethbuf->data);
466 }
467
468
469 void* NyLPC_cMiMicIpNetIf_releaseTxBuf(void* i_buf)
470 {
471     //排他処理をして、メモリを開放する。
472     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
473     NyLPC_cMutex_lock(&(inst->_mutex));
474     //ペイロードの位置から、メモリブロックを再生。
475     NyLPC_iEthernetDevice_releaseTxBuf(inst->_ethif,((struct NyLPC_TEthernetIIHeader*)i_buf)-1);
476     NyLPC_cMutex_unlock(&(inst->_mutex));
477     return NULL;
478 }
479
480
481
482
483
484
485
486
487
488 /**
489  * イーサネットフレームを送信します。
490  * この関数はiptaskで実行される関数からのみ使用てください。
491  * @i_buf
492  * イーサネットフレームを格納したメモリです。
493  * @i_len
494  * イーサネットペイロードのサイズです。
495  */
496 static void sendRawEthFrameNL(void* i_buf,NyLPC_TUInt16 i_len)
497 {
498     NyLPC_iEthernetDevice_sendTxEthFrame(
499         _NyLPC_TcMiMicIpNetIf_inst->_ethif,
500         ((struct NyLPC_TEthernetIIHeader*)i_buf)-1,
501         i_len);
502     return;
503 }
504 /**
505  * ロック状態で使用できるreleaseTxBuf。
506  * この関数はiptaskで実行される関数からのみ使用してください。
507  */
508 static void releaseTxBufNL(void* i_buf)
509 {
510     //ペイロードの位置から、メモリブロックを再生。
511     NyLPC_iEthernetDevice_releaseTxBuf(
512         _NyLPC_TcMiMicIpNetIf_inst->_ethif,
513         ((struct NyLPC_TEthernetIIHeader*)i_buf)-1);
514     return;
515 }
516 /**
517  * マルチキャスとアドレスへ変換する。
518  */
519 static void ip2MulticastEmacAddr(const struct NyLPC_TIPv4Addr* i_addr,struct NyLPC_TEthAddr* o_emac)
520 {
521     NyLPC_TUInt32 n=NyLPC_htonl(i_addr->v);
522     o_emac->addr[0]=0x01;
523     o_emac->addr[1]=0x00;
524     o_emac->addr[2]=0x5E;
525     o_emac->addr[3]=((n>>16) & 0x7f);
526     o_emac->addr[4]=((n>> 8) & 0xff);
527     o_emac->addr[5]=(n & 0xff);
528     return;
529 };
530
531 /**
532  * ペイロードをIPパケットとしてネットワークへ送出します。
533  * コール前に、必ずロックしてから呼び出してください。
534  * @param i_eth_payload
535  * allocTxBufで確保したメモリを指定してください。
536  * ペイロードには、TCP/IPパケットを格納します。
537  */
538 static NyLPC_TBool sendIPv4Tx(struct TEthPacket* i_eth_buf)
539 {
540     NyLPC_TcMiMicIpNetIf_t* inst=_NyLPC_TcMiMicIpNetIf_inst;
541     struct NyLPC_TEthAddr emac;
542     NyLPC_TUInt16 tx_len;
543     const struct NyLPC_TEthAddr* eth_dest;
544     //ペイロードのアドレスから、イーサネットフレームバッファのアドレスを復元
545
546     if(NyLPC_TIPv4Addr_isEqual(&(i_eth_buf->data.ipv4.destipaddr),&NyLPC_TIPv4Addr_BROADCAST)) {
547         //ブロードキャストならそのまま
548         eth_dest=&NyLPC_TEthAddr_BROADCAST;
549     }else if(NyLPC_TIPv4Addr_isEqualWithMask(&(i_eth_buf->data.ipv4.destipaddr),&NyLPC_TIPv4Addr_MULTICAST,&NyLPC_TIPv4Addr_MULTICAST_MASK)){
550         //マルチキャスト
551         ip2MulticastEmacAddr(&(i_eth_buf->data.ipv4.destipaddr),&emac);
552         eth_dest=&emac;
553     }else{
554         //LocalIP以外ならdefaultRootへ変換
555         eth_dest=NyLPC_cIPv4Arp_IPv4toEthAddr(
556             &inst->_arp,
557             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));
558         //IP->MAC変換をテスト。
559         if(eth_dest==NULL){
560             return NyLPC_TBool_FALSE;
561         }
562     }
563     //変換可能なら、イーサネットヘッダを更新して、送信処理へ。
564     tx_len=NyLPC_TEthernetIIHeader_setIPv4Tx(&(i_eth_buf->header),&(inst->_netinfo.current_config->eth_mac),eth_dest);
565     NyLPC_iEthernetDevice_sendTxEthFrame(inst->_ethif,i_eth_buf,tx_len);
566     return NyLPC_TBool_TRUE;
567 }
568
569 static NyLPC_TBool isInitService(void)
570 {
571         return _NyLPC_TcMiMicIpNetIf_inst!=NULL;
572 }
573
574 //--------------------------------------------------------------------------------
575 //
576 //      NetIF Interface
577 //
578 //--------------------------------------------------------------------------------
579
580
581 //--------------------------------------------------------------------------------
582 // ソケットテーブル
583 //--------------------------------------------------------------------------------
584
585 #define FLAGS_USED      0x00000001
586
587 struct TTcpTable
588 {
589         NyLPC_TUInt32 flags;
590         NyLPC_TcMiMicIpTcpSocket_t socket;
591         NyLPC_TUInt8 rxbuf[NyLPC_cMiMicIpNetIf_config_TCPSOCKET_RX_BUFFER_SIZE];
592 };
593 struct TUdpTable
594 {
595         NyLPC_TUInt32 flags;
596         NyLPC_TcMiMicIpUdpSocket_t socket;
597         NyLPC_TUInt8 rxbuf[NyLPC_cMiMicIpNetIf_config_UDPSOCKET_RX_BUFFER_SIZE];
598 };
599 struct TUdpNBTable
600 {
601         NyLPC_TUInt32 flags;
602         NyLPC_TcMiMicIpUdpSocket_t socket;
603 };
604 struct TTcpListenerTable
605 {
606         NyLPC_TUInt32 flags;
607         NyLPC_TcMiMicIpTcpListener_t listener;
608 };
609
610
611
612 static struct TTcpTable tcp_socket_table[NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX];
613 static struct TUdpTable udp_socket_table[NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX];
614 static struct TUdpNBTable udp_socket_nb_table[NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX];
615 static struct TTcpListenerTable tcp_listener_table[NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX];
616
617 NyLPC_TcMiMicIpTcpListener_t* NyLPC_cMiMicIpNetIf_getListenerByPeerPort(NyLPC_TUInt16 i_port)
618 {
619     int i;
620     //一致するポートを検索して、acceptをコールする。
621     for(i=NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX-1;i>=0;i--){
622         if((tcp_listener_table[i].flags&FLAGS_USED)==0){
623             continue;
624         }
625         if(tcp_listener_table[i].listener._port!=i_port){
626             continue;
627         }
628         return &tcp_listener_table[i].listener;
629     }
630     return NULL;
631 }
632
633 /**
634  * 指定番号のTCPポートが未使用かを返す。
635  * @return
636  * i_lport番のポートが未使用であればTRUE
637  */
638 NyLPC_TBool NyLPC_cMiMicIpNetIf_isClosedTcpPort(NyLPC_TUInt16 i_lport)
639 {
640     int i;
641     //未使用のTCPソケット?
642     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
643         if(     ((tcp_socket_table[i].flags&FLAGS_USED)!=0) &&
644                         (NyLPC_cMiMicIpTcpSocket_getLocalPort(&tcp_socket_table[i].socket)==i_lport)&&
645                         (!NyLPC_cMiMicIpTcpSocket_isClosed(&tcp_socket_table[i].socket))){
646                 //ポート使用中
647                 return NyLPC_TBool_FALSE;
648         }
649     }
650     for(i=NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX-1;i>=0;i--){
651         if(     ((tcp_listener_table[i].flags&FLAGS_USED)!=0) &&
652                         (NyLPC_cMiMicIpTcpListener_getLocalPort(&tcp_listener_table[i].listener)==i_lport)){
653                 //ポート使用中
654                 return NyLPC_TBool_FALSE;
655         }
656     }
657     return NyLPC_TBool_TRUE;
658 }
659
660 /**
661  * 条件に一致する、アクティブなTCPソケットオブジェクトを取得します。
662  * この関数は、ローカルIPが一致していると仮定して検索をします。
663  * @param i_rip
664  * リモートIPアドレスを指定します。
665  */
666 NyLPC_TcMiMicIpTcpSocket_t* NyLPC_cMiMicIpNetIf_getMatchTcpSocket(
667     NyLPC_TUInt16 i_lport,struct NyLPC_TIPv4Addr i_rip,NyLPC_TUInt16 i_rport)
668 {
669     NyLPC_TcMiMicIpTcpSocket_t* tp;
670     int i;
671     //一致するポートを検索
672     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
673         if((tcp_socket_table[i].flags&FLAGS_USED)==0){
674                 continue;
675         }
676                 if(NyLPC_cMiMicIpTcpSocket_isClosed(&tcp_socket_table[i].socket)){
677                 continue;
678                 }
679                 tp=&tcp_socket_table[i].socket;
680         //パラメータの一致チェック
681         if(i_lport!=tp->uip_connr.lport || i_rport!= tp->uip_connr.rport || i_rip.v!=tp->uip_connr.ripaddr.v)
682         {
683             continue;
684         }
685         return tp;
686     }
687     return NULL;
688 }
689 NyLPC_TcMiMicIpUdpSocket_t* NyLPC_cMiMicIpNetIf_getMatchUdpSocket(
690     NyLPC_TUInt16 i_lport)
691 {
692     int i;
693     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
694         if((udp_socket_table[i].flags&FLAGS_USED)==0){
695                 continue;
696         }
697         if(i_lport!=udp_socket_table[i].socket.uip_udp_conn.lport){
698                 continue;
699         }
700         //unicast
701         return &udp_socket_table[i].socket;
702     }
703     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
704         if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
705                 continue;
706         }
707         if(i_lport!=udp_socket_nb_table[i].socket.uip_udp_conn.lport){
708                 continue;
709         }
710         //unicast
711         return &udp_socket_nb_table[i].socket;
712     }
713     return NULL;
714 }
715 NyLPC_TcMiMicIpUdpSocket_t* NyLPC_cMiMicIpNetIf_getMatchMulticastUdpSocket(
716     const struct NyLPC_TIPv4Addr* i_mcast_ip,
717     NyLPC_TUInt16 i_lport)
718 {
719     int i;
720     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
721         if((udp_socket_table[i].flags&FLAGS_USED)==0){
722                 continue;
723         }
724         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))))
725         {
726             continue;
727         }
728         return &udp_socket_table[i].socket;
729     }
730     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
731         if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
732                 continue;
733         }
734         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))))
735         {
736             continue;
737         }
738         return &udp_socket_nb_table[i].socket;
739     }
740     return NULL;
741 }
742
743
744 void NyLPC_cMiMicIpNetIf_callPeriodic(void)
745 {
746     int i;
747     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
748         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
749             NyLPC_cMiMicIpUdpSocket_periodic(&udp_socket_table[i].socket);
750         }
751     }
752     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
753         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
754             NyLPC_cMiMicIpUdpSocket_periodic(&udp_socket_nb_table[i].socket);
755         }
756     }
757     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
758         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
759             NyLPC_cMiMicIpTcpSocket_periodic(&tcp_socket_table[i].socket);
760         }
761     }
762 }
763 void NyLPC_cMiMicIpNetIf_callSocketStart(
764         const NyLPC_TcIPv4Config_t* i_cfg)
765 {
766     int i;
767     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
768         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
769             NyLPC_cMiMicIpUdpSocket_startService(&udp_socket_table[i].socket,i_cfg);
770         }
771     }
772     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
773         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
774             NyLPC_cMiMicIpUdpSocket_startService(&udp_socket_nb_table[i].socket,i_cfg);
775         }
776     }
777     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
778         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
779             NyLPC_cMiMicIpTcpSocket_startService(&tcp_socket_table[i].socket,i_cfg);
780         }
781     }
782 }
783 void NyLPC_cMiMicIpNetIf_callSocketStop(void)
784 {
785     int i;
786     for(i=NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX-1;i>=0;i--){
787         if((udp_socket_table[i].flags&FLAGS_USED)!=0){
788             NyLPC_cMiMicIpUdpSocket_stopService(&udp_socket_table[i].socket);
789         }
790     }
791     for(i=NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX-1;i>=0;i--){
792         if((udp_socket_nb_table[i].flags&FLAGS_USED)!=0){
793             NyLPC_cMiMicIpUdpSocket_stopService(&udp_socket_nb_table[i].socket);
794         }
795     }
796     for(i=NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX-1;i>=0;i--){
797         if((tcp_socket_table[i].flags&FLAGS_USED)!=0){
798             NyLPC_cMiMicIpTcpSocket_stopService(&tcp_socket_table[i].socket);
799         }
800     }
801 }
802
803
804
805 //--------------------------------------------------------------------------------
806 // インタフェイス関数
807
808 static NyLPC_TiTcpSocket_t* createTcpSocetEx(NyLPC_TSocketType i_socktype)
809 {
810         NyLPC_TUInt16 i;
811         switch(i_socktype){
812         case NyLPC_TSocketType_TCP_HTTP:
813         case NyLPC_TSocketType_TCP_NORMAL:
814                 //空きソケットの探索
815                 for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX;i++){
816                         //未使用なソケットを得る
817                         if((tcp_socket_table[i].flags&FLAGS_USED)==0){
818                                 if(!NyLPC_cMiMicIpTcpSocket_initialize(&tcp_socket_table[i].socket,tcp_socket_table[i].rxbuf,NyLPC_cMiMicIpNetIf_config_TCPSOCKET_RX_BUFFER_SIZE)){
819                                         return NULL;
820                                 }
821                                 //ソケットを使用中に
822                                 tcp_socket_table[i].flags|=FLAGS_USED;
823                                 return &(tcp_socket_table[i].socket._super);
824                         }
825                 }
826                 break;
827         default:
828                 break;
829         }
830         return NULL;
831 }
832
833 static NyLPC_TiUdpSocket_t* createUdpSocetEx(NyLPC_TUInt16 i_port,NyLPC_TSocketType i_socktype)
834 {
835         NyLPC_TUInt16 i;
836         switch(i_socktype){
837         case NyLPC_TSocketType_UDP_NORMAL:
838                 //空きソケットの探索
839                 for(i=0;i<NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX;i++){
840                         //未使用なソケットを得る
841                         if((udp_socket_table[i].flags&FLAGS_USED)==0){
842                                 if(!NyLPC_cMiMicIpUdpSocket_initialize(&udp_socket_table[i].socket,i_port,udp_socket_table[i].rxbuf,NyLPC_cMiMicIpNetIf_config_UDPSOCKET_RX_BUFFER_SIZE)){
843                                         return NULL;
844                                 }
845                                 udp_socket_table[i].flags|=FLAGS_USED;
846                                 return &(udp_socket_table[i].socket._super);
847                         }
848                 }
849                 break;
850         case NyLPC_TSocketType_UDP_NOBUF:
851                 //空きソケットの探索
852                 for(i=0;i<NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX;i++){
853                         //未使用なソケットを得る
854                         if((udp_socket_nb_table[i].flags&FLAGS_USED)==0){
855                                 if(!NyLPC_cMiMicIpUdpSocket_initialize(&udp_socket_nb_table[i].socket,i_port,NULL,0)){
856                                         return NULL;
857                                 }
858                                 udp_socket_nb_table[i].flags|=FLAGS_USED;
859                                 return &(udp_socket_nb_table[i].socket._super);
860                         }
861                 }
862                 break;
863         default:
864                 break;
865         }
866         return NULL;
867 }
868 static NyLPC_TiTcpListener_t* createTcpListener(NyLPC_TUInt16 i_port)
869 {
870         NyLPC_TUInt16 i;
871         //空きソケットの探索
872         for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX;i++){
873                 //未使用なソケットを得る
874                 if((tcp_listener_table[i].flags&FLAGS_USED)==0){
875                         if(!NyLPC_cMiMicIpTcpListener_initialize(&tcp_listener_table[i].listener,i_port)){
876                                 return NULL;
877                         }
878                         //ソケットを使用中に
879                         tcp_listener_table[i].flags|=FLAGS_USED;
880                         return &(tcp_listener_table[i].listener._super);
881                 }
882         }
883         return NULL;
884 }
885
886
887 static const struct NyLPC_TiNetInterface_Interface _interface=
888 {
889         createTcpSocetEx,
890         createUdpSocetEx,
891         createTcpListener,
892         NyLPC_cMiMicIpNetIf_start,
893         NyLPC_cMiMicIpNetIf_stop,
894         NyLPC_cMiMicIpNetIf_sendArpRequest,
895         NyLPC_cMiMicIpNetIf_hasArpInfo,
896         isInitService,//NyLPC_TiNetInterface_isInitService isinitservice;
897         NyLPC_cMiMicIpNetIf_getInterfaceInfo
898 };
899 //--------------------------------------------------------------------------------
900 // インスタンスのリリース(protected)
901
902 void NyLPC_cMiMicIpNetIf_releaseTcpSocketMemory(const NyLPC_TcMiMicIpTcpSocket_t* i_inst)
903 {
904         NyLPC_TUInt16 i;
905         //空きソケットの探索
906         for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPSOCKET_MAX;i++){
907                 if((&tcp_socket_table[i].socket)==i_inst){
908                         tcp_socket_table[i].flags&=~FLAGS_USED;
909                         return;
910                 }
911         }
912         return;
913 }
914 void NyLPC_cMiMicIpNetIf_releaseUdpSocketMemory(const NyLPC_TcMiMicIpUdpSocket_t* i_inst)
915 {
916         NyLPC_TUInt16 i;
917         for(i=0;i<NyLPC_cMiMicIpNetIf_config_UDPSOCKET_MAX;i++){
918                 if((&udp_socket_table[i].socket)==i_inst){
919                         udp_socket_table[i].flags&=~FLAGS_USED;
920                         return;
921                 }
922         }
923         for(i=0;i<NyLPC_cMiMicIpNetIf_config_NB_UDPSOCKET_MAX;i++){
924                 if((&udp_socket_nb_table[i].socket)==i_inst){
925                         udp_socket_nb_table[i].flags&=~FLAGS_USED;
926                         return;
927                 }
928         }
929         return;
930 }
931 void NyLPC_cMiMicIpNetIf_releaseTcpListenerMemory(const NyLPC_TcMiMicIpTcpListener_t* i_inst)
932 {
933         NyLPC_TUInt16 i;
934         //空きソケットの探索
935         for(i=0;i<NyLPC_cMiMicIpNetIf_config_TCPLISTENER_MAX;i++){
936                 if((&tcp_listener_table[i].listener)==i_inst){
937                         tcp_listener_table[i].flags&=~FLAGS_USED;
938                         return;
939                 }
940         }
941         return;
942 }
943
944 static NyLPC_TcMiMicIpNetIf_t _netif;
945
946 const struct NyLPC_TiNetInterface_Interface* NyLPC_cMiMicIpNetIf_getNetInterface(void)
947 {
948         NyLPC_cMiMicIpNetIf_initialize(&_netif);
949         return &_interface;
950 }
951
952
953