Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
Diff: uip/NyLPC_cIPv4.cpp
- Revision:
- 0:142ee8b12fef
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uip/NyLPC_cIPv4.cpp Wed Jan 30 03:46:05 2013 +0000
@@ -0,0 +1,389 @@
+/*********************************************************************************
+ * PROJECT: MiMic
+ * --------------------------------------------------------------------------------
+ *
+ * This file is part of MiMic
+ * Copyright (C)2011 Ryo Iizuka
+ *
+ * MiMic is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For further information please contact.
+ * http://nyatla.jp/
+ * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>
+ *
+ *
+ * Parts of this file were leveraged from uIP:
+ *
+ * Copyright (c) 2001-2003, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "NyLPC_stdlib.h"
+#include "NyLPC_cIPv4.h"
+#include "NyLPC_cIPv4Payload_protected.h"
+#include "NyLPC_cTcpSocket_protected.h"
+#include "NyLPC_cTcpListener_protected.h"
+#include "NyLPC_cIPv4IComp_protected.h"
+#include "NyLPC_cUipService_protected.h"
+
+
+
+/****************************************************
+ * Listenerテーブルに関する宣言
+ ***************************************************/
+
+
+
+#define cListenerTbl_initialize(i_inst,buf) NyLPC_cPtrTbl_initialize(i_inst,buf,NyLPC_cIPv4_MAX_TCP_LISTENER)
+
+/**
+ * i_peer番号に一致するリスナを返します。
+ */
+static NyLPC_TcTcpListener_t* cListenerTbl_getByPeerPort(NyLPC_TcPtrTbl_t* i_inst,NyLPC_TUInt16 i_peer_port)
+{
+ NyLPC_TcTcpListener_t** p=(NyLPC_TcTcpListener_t**)(i_inst->buf);
+ int i;
+ //一致するポートを検索して、acceptをコールする。
+ for(i=i_inst->size-1;i>=0;i--){
+ if(p[i]==NULL){
+ continue;
+ }
+ if(p[i]->_port!=i_peer_port){
+ continue;
+ }
+ return p[i];
+ }
+ return NULL;
+}
+
+/****************************************************
+ * Socketテーブルに関する宣言
+ ***************************************************/
+
+#define cSocketTbl_initialize(i_inst,buf) NyLPC_cPtrTbl_initialize(i_inst,buf,NyLPC_cIPv4_MAX_TCP_SOCKET)
+
+
+/**
+ * 条件に一致する、アクティブなソケットオブジェクトを取得します。
+ * この関数は、ローカルIPが一致していると仮定して検索をします。
+ * @param i_rip
+ * リモートIPアドレスを指定します。
+ */
+static NyLPC_TcTcpSocket_t* cSocketTbl_getMatchSocket(
+ NyLPC_TcPtrTbl_t* i_inst,
+ NyLPC_TUInt16 i_lport,
+ struct NyLPC_TIPv4Addr i_rip,
+ NyLPC_TUInt16 i_rport)
+{
+ NyLPC_TcTcpSocket_t** p=(NyLPC_TcTcpSocket_t**)(i_inst->buf);
+ int i;
+ //一致するポートを検索して、acceptをコールする。
+ for(i=i_inst->size-1;i>=0;i--){
+ if(p[i]==NULL){
+ continue;
+ }
+ if(p[i]->tcpstateflags==UIP_CLOSED){
+ continue;
+ }
+ //パラメータの一致チェック
+ if(i_lport!=p[i]->uip_connr.lport || i_rport!= p[i]->uip_connr.rport || i_rip.v!=p[i]->uip_connr.ripaddr.v)
+ {
+ continue;
+ }
+ return p[i];
+ }
+ return NULL;
+}
+/**
+ * テーブルにある有効なソケットのperiodicをすべて呼び出します。
+ */
+static void cSocketTbl_callPeriodic(
+ NyLPC_TcPtrTbl_t* i_inst)
+{
+ NyLPC_TcTcpSocket_t** p=(NyLPC_TcTcpSocket_t**)(i_inst->buf);
+ int i;
+ for(i=i_inst->size-1;i>=0;i--){
+ if(p[i]==NULL){
+ continue;
+ }
+ NyLPC_cTcpSocket_periodic(p[i]);
+ }
+}
+
+/**
+ * Static関数
+ */
+
+static NyLPC_TBool tcp_rx(
+ NyLPC_TcIPv4_t* i_inst,
+ NyLPC_TcIPv4Payload_t* i_ipp);
+
+/****************************************************
+ * NyLPC_cIPv4
+ ***************************************************/
+
+/**
+ * See Header file.
+ */
+void NyLPC_cIPv4_initialize(
+ NyLPC_TcIPv4_t* i_inst)
+{
+ //内部テーブルの初期化
+ cListenerTbl_initialize(&(i_inst->_listener_tbl),(void**)(i_inst->_listener_array_buf));
+ cSocketTbl_initialize(&(i_inst->_socket_tbl),(void**)(i_inst->_socket_array_buf));
+ //instanceの初期化
+ i_inst->_ref_config=NULL;
+ return;
+}
+
+/**
+ * See header file.
+ */
+void NyLPC_cIPv4_finalize(
+ NyLPC_TcIPv4_t* i_inst)
+{
+ return;
+}
+
+/**
+ * See header file.
+ */
+void NyLPC_cIPv4_start(
+ NyLPC_TcIPv4_t* i_inst,
+ const NyLPC_TcIPv4Config_t* i_ref_configlation)
+{
+ NyLPC_ArgAssert(i_ref_configlation!=NULL);
+ //リストの初期化、ここでするべき?しないべき?
+ i_inst->_ref_config=i_ref_configlation;
+ return;
+}
+
+/**
+ * See header file.
+ */
+void NyLPC_cIPv4_stop(
+ NyLPC_TcIPv4_t* i_inst)
+{
+ //実行タイミングが未設計。当分は使わないこと。
+ //新規ソケットの生成を打ち切って、すべてのソケットが停止するのを待つ?
+ i_inst->_ref_config=NULL;
+ return;
+}
+
+/**
+ * See header file.
+ */
+NyLPC_TBool NyLPC_cIPv4_addSocket(
+ NyLPC_TcIPv4_t* i_inst,
+ NyLPC_TcTcpSocket_t* i_sock)
+{
+ //当面、stop中しか成功しない。
+ NyLPC_Assert(!NyLPC_cUipService_isRun());
+ return NyLPC_cPtrTbl_add(&(i_inst->_socket_tbl),i_sock)>=0;
+}
+
+/**
+ * See header file.
+ */
+NyLPC_TBool NyLPC_cIPv4_removeSocket(
+ NyLPC_TcIPv4_t* i_inst,
+ NyLPC_TcTcpSocket_t* i_sock)
+{
+ NyLPC_TInt16 i;
+ NyLPC_Assert(!NyLPC_cUipService_isRun());
+ i=NyLPC_cPtrTbl_getIndex(&(i_inst->_socket_tbl),i_sock);
+ if(i>=0){
+ NyLPC_cPtrTbl_remove(&(i_inst->_socket_tbl),i);
+ return NyLPC_TBool_TRUE;
+ }
+ return NyLPC_TBool_FALSE;
+}
+
+/**
+ * See header file.
+ */
+NyLPC_TBool NyLPC_cIPv4_addListener(
+ NyLPC_TcIPv4_t* i_inst,
+ NyLPC_TcTcpListener_t* i_listener)
+{
+ //当面、stop中しか成功しない。
+ NyLPC_Assert(!NyLPC_cUipService_isRun());
+ return NyLPC_cPtrTbl_add(&(i_inst->_listener_tbl),i_listener)>=0;
+}
+
+/**
+ * See header file.
+ */
+NyLPC_TBool NyLPC_cIPv4_removeListener(
+ NyLPC_TcIPv4_t* i_inst,
+ NyLPC_TcTcpListener_t* i_listener)
+{
+ NyLPC_TInt16 i;
+ NyLPC_Assert(!NyLPC_cUipService_isRun());
+ i=NyLPC_cPtrTbl_getIndex(&(i_inst->_listener_tbl),i_listener);
+ if(i>=0){
+ NyLPC_cPtrTbl_remove(&(i_inst->_listener_tbl),i);
+ return NyLPC_TBool_TRUE;
+ }
+ return NyLPC_TBool_FALSE;
+}
+
+
+
+
+
+#define IS_START(i_inst) ((i_inst)->_ref_config!=NULL)
+
+/**
+ * 稼動時に、1s置きに呼び出す関数です。
+ */
+void NyLPC_cIPv4_periodec(NyLPC_TcIPv4_t* i_inst)
+{
+ cSocketTbl_callPeriodic(&(i_inst->_socket_tbl));
+}
+
+
+/**
+ * IPv4ペイロードを処理する関数。
+ * この関数は、パケット受信タスクから実行します。
+ * @param i_rx
+ * 先頭ポインタ。
+ * @return
+ * TRUEなら、i_rxに応答パケットをセットして返します。
+ */
+NyLPC_TBool NyLPC_cIPv4_rx(NyLPC_TcIPv4_t* i_inst,void* i_rx,NyLPC_TUInt16 i_rx_size)
+{
+ NyLPC_TcUipService_t* inst=_NyLPC_TcUipService_inst;
+ NyLPC_TcIPv4Payload_t ipv4;
+ //NOT開始状態なら受け付けないよ。
+ if(!IS_START(i_inst)){
+ NyLPC_OnErrorGoto(ERROR_DROP);
+ }
+
+ NyLPC_cIPv4Payload_initialize(&ipv4);
+ //IPフラグメントを読出し用にセットする。
+ if(!NyLPC_cIPv4Payload_setRxBuf(&ipv4,i_rx,i_rx_size))
+ {
+ NyLPC_OnErrorGoto(ERROR_DROP);
+ }
+ switch(ipv4.header->proto)
+ {
+ case UIP_PROTO_TCP:
+ //TCP受信処理
+ return tcp_rx(i_inst,&ipv4);
+ case UIP_PROTO_UDP:
+ // //uip_process_UDP();//実装したら解除いして
+ NyLPC_OnErrorGoto(ERROR_DROP);
+ case UIP_PROTO_ICMP:
+ if(!NyLPC_cIPv4IComp_rx(&(inst->_icomp),&ipv4)){
+ NyLPC_OnErrorGoto(ERROR_DROP);
+ }
+ return NyLPC_TBool_TRUE;
+ }
+ return NyLPC_TBool_FALSE;
+ERROR_DROP:
+ return NyLPC_TBool_FALSE;
+}
+
+
+/**********************************************************************
+ *
+ * public function
+ *
+ **********************************************************************/
+
+
+static NyLPC_TBool tcp_rx(
+ NyLPC_TcIPv4_t* i_inst,
+ NyLPC_TcIPv4Payload_t* i_ipp)
+{
+ NyLPC_TcTcpSocket_t* sock;
+ NyLPC_TcTcpListener_t* listener;
+
+ //自分自身のIPに対する呼び出し?
+ if(!NyLPC_TIPv4Addr_isEqual(&(i_ipp->header->destipaddr),&(i_inst->_ref_config->ip_addr)))
+ {
+ //自分以外のパケットはドロップ
+ goto DROP;
+ }
+ //チェックサムの計算
+ if((NyLPC_TIPv4Header_makeTcpChecksum(i_ipp->header) != 0xffff))
+ {
+ //受信エラーのあるパケットはドロップ
+ goto DROP;
+ }
+ //アクティブなソケットを探す。
+ sock=cSocketTbl_getMatchSocket(&(i_inst->_socket_tbl),i_ipp->payload.tcp->destport,i_ipp->header->srcipaddr,i_ipp->payload.tcp->srcport);
+ if(sock!=NULL)
+ {
+ //既存の接続を処理
+ return NyLPC_cTcpSocket_parseRx(sock,i_ipp);
+
+ }else{
+ //未知の接続
+ if(!NyLPC_cPtrTbl_hasEmpty(&(i_inst->_socket_tbl))){
+ //ソケットテーブルが不十分。RST送信
+ NyLPC_cIPv4Payload_setTcpReverseRstAck(i_ipp);
+ return NyLPC_TBool_TRUE;
+ }
+ //このポートに対応したListenerを得る。
+ listener=cListenerTbl_getByPeerPort(&(i_inst->_listener_tbl),i_ipp->payload.tcp->destport);
+ if(listener==NULL){
+ //Listen対象ではない。RST送信
+ NyLPC_cIPv4Payload_setTcpReverseRstAck(i_ipp);
+ return NyLPC_TBool_TRUE;
+ }
+ //リスナにソケットのバインドを依頼する。
+ sock=NyLPC_cTcpListener_makeSynRcvdSocket(listener,i_inst->_ref_config,i_ipp);
+ if(sock==NULL){
+ //Listen失敗。ドロップ
+ goto DROP;
+ }
+// //Socketの割当に成功。管理リストへ追加
+// NyLPC_AbortIfNot(NyLPC_cPtrTbl_add(&(i_inst->_socket_tbl),sock)>=0);
+ return NyLPC_TBool_FALSE;//LISTEN成功。送信データなし
+ }
+ return NyLPC_TBool_TRUE;
+DROP:
+ return NyLPC_TBool_FALSE;
+}
+
+
+
+
+
+
MiMic Webservice library