This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088

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

libMiMic(MiMic library for mbed)は、WebService機能を提供するSDKです。 mbedでWebAPIに対応したネットワークデバイスを簡単に作ることが出来ます。

libMiMicはMiMic projectで開発しています。MiMic projectについてはこちらをご覧ください。 http://nyatla.jp/mimic/wp/

構成

libMiMicはmbedRTOS上で動作し、ユーザアプリケーションにAPIを提供します。コアAPIはC言語で記述されていますが、使用頻度の高いものについてはmbed向けのC++APIが準備されています。

/media/uploads/nyatla/libmimic-sdk.png

※libMiMicはmbedの標準イーサネットドライバをしようしていません。

標準イーサネットドライバと同時に使用することはできません。

  • MiMicIP - IPv4スタックです。レテンシとメモリ消費量を抑えたuipベースのライブラリです。
  • ARP/ICMP/UDP/TCP - 基礎的なソケットAPIを提供します。APIは独自です。
  • HTTP/1.1 Server - HTTP/1.1に対応したサーバです。マルチセッション・Chunked・持続性接続に対応しています。
  • HTTP Modules - HTTP/1.1の機能モジュールです。以下のモジュールがあります。
    • ROM file provider - ROMに格納したファイルイメージを公開します。
    • File system provider - mbedファイルシステムを公開します。
    • Onchip configuration - プログラムフラッシュを利用して設定を保存します。
    • MiMicVM processor - RPCリクエスト(MiMicVM)を処理します。
    • FileUpload - ファイルアップロードを受け取ります。
    • URL decoder - HTTPリクエストを解析します。
    • UPnP handler -UPnPメッセージを処理します。
    • WebSocket - Websocketサーバです。
  • mDNS - マルチキャストDNSサービスです。
  • UPnP - UPnP/1.0の機能を提供します。UPnP handlerと協調して動作します。(現在はデバイス探索(SSDP)・デスクリプション(Description)のみ実装してあります。)
  • DHCP/APIPA - ゼロコンフィギュレーション用のモジュールです。
  • HTTP/1.1 Client
  • mbed C++ class library - mbed向けのC++CPIです。C言語のものより簡単です。

対応機種

  • mbed(mbed LPC1768)
  • LPCXpresso1769

プログラム

Import programMiMicRemoteMCU-for-Mbed

MiMic RemoteMCU for mbed. This program provides MCU control API over REST API. It can control MCU from Javascript,PHP or any HTTP rest client directly. And, The application has self development environment.

Import programMbedFileServer

The program publishes files at local directory and SD filesystem. It is a full-fledged webServer somewhat.

サンプル

Import programMiMicSimpleHttpd

This is a simplest HTTP server made ​​of libMiMic. It will echo back a request path.

Import programUPnPBasicDevice

Simplest UPnP basic device example. This program to run UPnP basic device on the mbed.

Import programWebSocketSample

MiMicSDK Websocket module sample program.

Import programHttpClientSamlpe

A http client sample program.

Import programTcpSocketClientSamlpe

MiMicSDK Tcp client socket sample program.

Import programUdpSocketSamlpe

Udp socket sample program. This program will send back the received packet.

チュートリアル

English

libMiMic(MiMic library for mbed) is SDK which provides Webservice functions. It can be created networking device easily using mbed.

See more MiMic information, See MiMic project website. http://nyatla.jp/mimic/wp/

Structure

libMiMic run on mbed RTOS and provides networking API to user application. This library has C++ class API for the mbed, and low-level C language API.

/media/uploads/nyatla/libmimic-sdk.png

For WebService general, it can be written in a simple C + + API.

libMiMic does not have the standard Ethernet driver of mbed. It is not possible that will be used with the standard Ethernet driver.

  • MiMicIP - IPv4 protocol stack. This is based uip which is reduced memory and latency.
  • ARP / ICMP / UDP / TCP - Those are provide basic IP protocols.
  • HTTP/1.1 Server - The Http server compatible HTTP/1.1. It supports multi-session, chunked transport, persistent connection.
  • HTTP Modules - There are addon-module for HTTP server. The following modules.
    • ROM file module - Publish the file images in ROM.
    • File system module - Publish thefiles in mbed file system.
    • Onchip configuration module - To save the network settings to the program flash via REST.
    • MiMicVM module - To handle the (MiMicVM) RPC request.
    • FileUpload module - Accept a file via HTTP POST.
    • URL dedoce module - A versatility URL decoder.
    • UPnP handle module - To handle UPnP messages.
    • UPnP - This provides UPnP/1.0 device functions. It works together with UPnP handler.
    • Websocket - websocket (version13) server
  • mDNS Service - DNS-SD protocol server.
  • UPnP - This provides UPnP/1.0 device functions which works with UPnP handler. (You have been implemented (SSDP) ? description only (Description) device search now.) It is a module zero configuration for - DHCP / APIPA. mbed C + + class library - C of mbed for + + is the CPI. It is simple than that of the C language.
  • DHCP/APIPA - It support zero-cpnfigulation.
  • mbed C++ class library. Almost APIs for Web applications are available.
  • HTTP/1.1 Client

Supported target

  • mbed(mbed LPC1768)
  • LPCXpresso1769

Application

Import programMiMicRemoteMCU-for-Mbed

MiMic RemoteMCU for mbed. This program provides MCU control API over REST API. It can control MCU from Javascript,PHP or any HTTP rest client directly. And, The application has self development environment.

Import programMbedFileServer

The program publishes files at local directory and SD filesystem. It is a full-fledged webServer somewhat.

Sample

Import programMiMicSimpleHttpd

This is a simplest HTTP server made ​​of libMiMic. It will echo back a request path.

Import programUPnPBasicDevice

Simplest UPnP basic device example. This program to run UPnP basic device on the mbed.

Import programWebSocketSample

MiMicSDK Websocket module sample program.

Import programHttpClientSamlpe

A http client sample program.

Import programTcpSocketClientSamlpe

MiMicSDK Tcp client socket sample program.

Import programUdpSocketSamlpe

Udp socket sample program. This program will send back the received packet.

Tutorial

Revision:
109:18f12ac01097
Parent:
108:8dae2a2682e7
Child:
110:257739f9b31e
--- a/core/uip/NyLPC_cTcpSocket.c	Thu Nov 13 14:06:19 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1492 +0,0 @@
-/*********************************************************************************
- * 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>
- *
- *********************************************************************************/
-#include "NyLPC_cTcpSocket_protected.h"
-#include "NyLPC_stdlib.h"
-#include "NyLPC_cUipService_protected.h"
-
-
-static NyLPC_TUInt32 iss32=3939;
-#define SIZE_OF_IPv4_TCPIP_HEADER 40
-
-/**
- * TCPのRTOの最大値。
- * ms単位である。
- * defaultは64SEC
- */
-#define UIP_IP_RTO_MAX_RTO 64000
-/**
- * TCPのRTOの初期値。
- * ms単位である。
- * 伝送路の特性に合わせて調整すること。
- */
-#define UIP_TCP_RTO_INITIAL 3000
-
-/**
- * CONNECTION時のRTO
- */
-#define UIP_TCP_RTO_CONNECTION_INITIAL 200
-
-/**
- * 下限値
- */
-#define UIP_TCP_RTO_MINIMUM 100
-
-
-/**
- * for Debug
- * RTOの情報をログ領域に取る。
- */
-#ifdef RTO_LOG
-    NyLPC_TUInt32 rto_log[256];
-    int rto_log_st=0;
-    #define DEBUG_RTO_LOG(i_inst) if(rto_log_st<256){rto_log[rto_log_st++]=i_inst->uip_connr.current_rto32;};
-#else
-    #define DEBUG_RTO_LOG(i_inst)
-#endif
-
-//#define lockResource(i_inst) NyLPC_cMutex_lock(&((i_inst)->_smutex))
-//#define unlockResource(i_inst) NyLPC_cMutex_unlock(&((i_inst)->_smutex))
-#define lockResource(i_inst) NyLPC_cMutex_lock(NyLPC_cIPv4_getSockMutex(((i_inst)->_super._parent_ipv4)))
-#define unlockResource(i_inst) NyLPC_cMutex_unlock(NyLPC_cIPv4_getSockMutex(((i_inst)->_super._parent_ipv4)))
-
-static void sendRst(NyLPC_TcTcpSocket_t* i_inst);
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-//  Packet writer
-//
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-
-/**
- * TCPヘッダに値をセットする。checksum,wndは0初期化する。
- */
-static void setTcpTxHeader(struct NyLPC_TTcpHeader* i_struct,NyLPC_TUInt8 i_flag,const struct uip_conn* i_conn)
-{
-    i_struct->flags    = i_flag;
-    //sorce & destination port
-    i_struct->srcport  = i_conn->lport;
-    i_struct->destport = i_conn->rport;
-    //ACK number
-    i_struct->ackno32  = NyLPC_htonl(i_conn->rcv_nxt32);
-    //Seq Number
-    i_struct->seqno32  = NyLPC_htonl(i_conn->snd_nxt32);
-    //uip_func_tcp_send_noconn(BUF);
-    i_struct->urgp[0]  = i_struct->urgp[1] = 0;
-    i_struct->tcpchksum= 0;
-}
-
-static void setTxPacket(const NyLPC_TcTcpSocket_t* i_inst,void* i_tx_buf,NyLPC_TUInt8 i_tcpf,const void* i_buf,NyLPC_TUInt16 i_len)
-{
-    struct NyLPC_TIPv4Header*   iph;
-    struct NyLPC_TTcpHeader*    tcph;
-    NyLPC_TUInt8 iph_word=0x05;
-    NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
-    //IPヘッダの更新
-    iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
-    iph->vhl=0x40|(0x0f&iph_word);
-    iph->destipaddr=i_inst->uip_connr.ripaddr;
-    iph->srcipaddr =*(i_inst->uip_connr.lipaddr);
-    NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
-    //TCPヘッダの更新
-    tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
-
-
-    //SYNが有るならMSSの書き込み
-    if((TCP_SYN & i_tcpf)){
-        tcph_word+=((TCP_OPT_MSS_LEN) / 4);
-        NyLPC_TTcpHeader_setMmsOpt(((NyLPC_TUInt8*)(tcph+1)),i_inst->uip_connr.default_mss);
-    }
-    tcph->tcpoffset=(tcph_word<<4);
-    setTcpTxHeader(tcph,i_tcpf,&(i_inst->uip_connr));
-
-    //最終的なパケットサイズと必要ならペイロードを書き込み
-    if(i_buf!=NULL){
-        iph->len16=NyLPC_htons(i_len+(iph_word+tcph_word)*4);
-        memcpy(((NyLPC_TUInt8*)i_tx_buf)+((iph_word+tcph_word)*4),i_buf,i_len);
-    }else{
-        iph->len16=NyLPC_htons((iph_word+tcph_word)*4);
-    }
-    //WND設定
-    tcph->wnd16=NyLPC_htons(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf)));
-    //Checksumの生成
-    tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
-    iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
-    return;
-}
-
-/**
- * IP/TCPヘッダが40バイト固定として、i_tx_buf+40の位置にあるペイロードに対するIP/TCPヘッダを書き込みます。
- */
-static void setTxPacketHeader(const NyLPC_TcTcpSocket_t* i_inst,void* i_tx_buf,NyLPC_TUInt8 i_tcpf,NyLPC_TUInt16 i_len)
-{
-    struct NyLPC_TIPv4Header*   iph;
-    struct NyLPC_TTcpHeader*    tcph;
-    NyLPC_TUInt8 iph_word=0x05;
-    NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
-    //IPヘッダの更新
-    iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
-    iph->vhl=0x40|(0x0f&iph_word);
-    iph->destipaddr=i_inst->uip_connr.ripaddr;
-    iph->srcipaddr =*(i_inst->uip_connr.lipaddr);
-    NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
-
-    //TCPヘッダの更新
-    tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
-    tcph->tcpoffset=(tcph_word<<4);
-    setTcpTxHeader(tcph,i_tcpf,&(i_inst->uip_connr));
-
-    //最終的なパケットサイズと必要ならペイロードを書き込み
-    iph->len16=NyLPC_htons(i_len+(iph_word+tcph_word)*4);
-    //WND設定
-    tcph->wnd16=NyLPC_htons(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf)));
-    //Checksumの生成
-    tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
-    iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
-    return;
-}
-
-
-
-
-
-////////////////////////////////////////////////////////////////////////////////////////////////////
-//
-//  Mainclass::private
-//
-////////////////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * ACK番号を更新する。
- * @param i_ackno
- * ネットワークオーダーのACK番号
- */
-static void updateAckNo(void* i_tx_buf,NyLPC_TUInt32 i_ackno)
-{
-    struct NyLPC_TIPv4Header*   iph=(struct NyLPC_TIPv4Header*)i_tx_buf;
-    struct NyLPC_TTcpHeader*    tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)i_tx_buf)+NyLPC_TIPv4Header_getHeaderLength(iph));
-
-/*  union{
-        NyLPC_TUInt32 l;
-        NyLPC_TUInt8 b[4];
-    }old_ack,new_ack;
-    NyLPC_TUInt16 v1;
-    //checksumの計算
-    old_ack.l=i_inst->payload.tcp->ackno32;//古いACK番号
-    new_ack.l=i_ackno;//新しいACK番号
-    v1=NyLPC_ntohs(~(i_inst->payload.tcp->tcpchksum));//1の補数を取って、ホストオーダーに戻す。
-    //減算
-    v1=sub16c(v1,(old_ack.b[0]<<8)+old_ack.b[1]);
-    v1=sub16c(v1,(old_ack.b[2]<<8)+old_ack.b[3]);
-    //加算
-    v1=add16c(v1,(new_ack.b[0]<<8)+new_ack.b[1]);
-    v1=add16c(v1,(new_ack.b[2]<<8)+new_ack.b[3]);
-    v1=~NyLPC_htons(v1);*/
-NyLPC_Trace();
-    tcph->ackno32=i_ackno;
-NyLPC_Trace();
-    tcph->tcpchksum = 0;
-NyLPC_Trace();
-    tcph->tcpchksum = ~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
-NyLPC_Trace();
-
-/*
-    if((i_inst->payload.tcp->tcpchksum!=v1)){
-        NyLPC_Warning();
-    }*/
-}
-
-
-
-/**
- * 指定した送信パケットがACK済であるか調べる。
- */
-static NyLPC_TBool isPacketAcked(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq)
-{
-    int rp;
-    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
-    rp=i_inst->txbuf.rp;
-    while(rp!=i_inst->txbuf.wp){
-        if(q[rp].ackno==i_sq){
-            return NyLPC_TBool_FALSE;
-        }
-        rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
-    }
-    return NyLPC_TBool_TRUE;
-}
-/**
- * 送信キューからi_sq以前に送信したパケットを除外して、残り個数を返却する。
- */
-static int getNumOfSending(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq)
-{
-    int rp,n;
-    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
-    rp=i_inst->txbuf.rp;
-    n=0;
-    while(rp!=i_inst->txbuf.wp){
-        if(q[rp].ackno==i_sq){
-            return n;
-        }
-        n++;
-        rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
-    }
-    return n;
-}
-/**
- * この関数は、コネクションをリセットします。
- * ロック状態でコールしてください。
- * 関数は、現在バッファにある再送信待ちデータを開放します。
- */
-static void resetTxQWithUnlock(NyLPC_TcTcpSocket_t* i_inst)
-{
-    int i,l;
-    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
-    void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
-
-    l=0;
-    while(i_inst->txbuf.rp!=i_inst->txbuf.wp){
-        dlist[l]=q[i_inst->txbuf.rp].packet;
-        l++;
-        i_inst->txbuf.rp=(i_inst->txbuf.rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
-    }
-    i_inst->txbuf.rp=i_inst->txbuf.wp=0;
-    //ロック解除
-    unlockResource(i_inst);
-    //セーブしたバッファを開放
-    for(i=0;i<l;i++){
-        NyLPC_cUipService_releaseTxBuf(dlist[i]);
-    }
-    return;
-}
-/**
- * TXバッファの再送パケットのACK番号を更新します。
- * ロックして実行してください。
- * @param i_ackno
- * ネットワークオーダーのACK番号
- */
-static void updateTxAck(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_ackno)
-{
-    NyLPC_TUInt8 rp;
-    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
-    NyLPC_ArgAssert(i_inst!=NULL);
-    rp=i_inst->txbuf.rp;
-    while(rp!=i_inst->txbuf.wp){
-        updateAckNo(q[rp].packet,i_ackno);
-        rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
-    }
-}
-
-/**
- * RTOの予測関数
- */
-static void estimateRTO(NyLPC_TcTcpSocket_t* i_inst,int s,int n)
-{
-    NyLPC_TcStopwatch_t sw;
-    NyLPC_TUInt32 cr_rtt_min,cr_rtt_max,sk_rto,new_rto,w;
-    int i;
-    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
-    NyLPC_cStopwatch_initialize(&sw);
-
-    sk_rto=i_inst->uip_connr.current_rto32;
-    //ACKされたパケットの個数は?
-    switch(n){
-    case 1:
-        NyLPC_cStopwatch_set(&sw,q[s].tick_of_sent);
-        cr_rtt_min=NyLPC_cStopwatch_elapseInMsec(&sw);
-        if(sk_rto<cr_rtt_min){
-            //現在のRTOよりも大きい→再送があった。(再送の理由が回線遅延によるものかわからないので、基本RTOを25%増やす。)
-            new_rto=sk_rto*10/8;
-        }else if(sk_rto/4<cr_rtt_min){
-            //現在のRTOの1/4< n < 現在のRTO 想定内の変動。1/8
-            new_rto=(sk_rto+(cr_rtt_min*3*7))/8;
-        }else{
-            //現在の1/4以下。RTOを再計算。 RTOが大きすぎるので再計算。(計測値を優先した現在値との平均値)
-            new_rto=(sk_rto+(cr_rtt_min*3*3))/4;
-        }
-        break;
-    default:
-        //複数のパケットなら、最大と最小の時刻を得る。
-        NyLPC_cStopwatch_set(&sw,q[s].tick_of_sent);
-        cr_rtt_min=cr_rtt_max=NyLPC_cStopwatch_elapseInMsec(&sw);
-        for(i=1;i<n;i++){
-            NyLPC_cStopwatch_set(&sw,q[(s+i)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ].tick_of_sent);
-            w=NyLPC_cStopwatch_elapseInMsec(&sw);
-            if(cr_rtt_min>w){
-                cr_rtt_min=w;
-            }
-            if(cr_rtt_max<w){
-                cr_rtt_max=w;
-            }
-        }
-        if(sk_rto<cr_rtt_min && sk_rto<cr_rtt_max){
-            //最大値,最小値とも現在のRTTより大きい→低速な回線を検出。
-            new_rto=cr_rtt_max*10/8;//最大経過時間の25%増しの時間を設定。
-        }else if(sk_rto/4<cr_rtt_min){
-            //現在のRTOの1/4< n < 現在のRTO 想定範囲内。1/8の加重平均で速度計算。
-            new_rto=(sk_rto+(cr_rtt_min*3*7))/8;
-        }else{
-            //現在の1/4以下。RTOが大きすぎるので再計算。(計測値を優先した加重平均)
-            new_rto=(sk_rto+(cr_rtt_min*3*3))/4;
-        }
-        break;
-    }
-    NyLPC_cStopwatch_finalize(&sw);
-    if(new_rto<UIP_TCP_RTO_MINIMUM){
-        new_rto=UIP_TCP_RTO_MINIMUM;
-    }
-    i_inst->uip_connr.current_rto32=new_rto;
-}
-
-/**
- * TXキューから、入力されたシーケンス番号より前のパケットを除外します。
- * リングバッファのrp->wp-1までをチェックして、sqに等しいi_sq以前のパケットバッファをo_dlistへ返します。
- *
- */
-static int updateTxQByIndex(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,void* o_dlist[])
-{
-    int rp,n;
-    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
-    //ロック状態なう
-    rp=i_inst->txbuf.rp;
-    n=0;
-    //This is debug
-    DEBUG_RTO_LOG(i_inst);
-
-    while(rp!=i_inst->txbuf.wp){
-        o_dlist[n]=q[rp].packet;
-        if(q[rp].ackno==i_sq){
-            //i_inst->txbuf.rp->rpのパケットのRTOからbaseRTOの値を再計算。
-            estimateRTO(i_inst,i_inst->txbuf.rp,n+1);
-            i_inst->txbuf.rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
-            return n+1;
-        }
-        n++;
-        rp=(rp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
-    }
-    return 0;
-}
-
-
-
-/**
- * 空きキューを1個返します。
- * 空きキューの
- */
-static struct NyLPC_TcTcpSocket_TxQItem* getTxQ(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TcStopwatch_t* i_timer)
-{
-    int i;
-    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
-    do{
-        //クローズドに遷移してしまったら、エラーである。
-        if(i_inst->tcpstateflags==UIP_CLOSED){
-            return NULL;
-        }
-        //キューの空きをチェック。wp+1==rpなら、キューがいっぱい。rp==wpなら、キューが空。
-        if(((i_inst->txbuf.wp+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ)==i_inst->txbuf.rp){
-            //一時的なアンロック
-            unlockResource(i_inst);
-            //タスクスイッチ
-            NyLPC_cThread_yield();
-            //ロック
-            lockResource(i_inst);
-            continue;
-        }
-        i=i_inst->txbuf.wp;
-        i_inst->txbuf.wp=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ;
-        return &(q[i]);
-    }while(!NyLPC_cStopwatch_isExpired(i_timer));
-    //失敗。タイムアウト。
-    return NULL;
-}
-
-
-
-
-
-
-/**********************************************************************
- * public 関数
- **********************************************************************/
-
-NyLPC_TBool NyLPC_cTcpSocket_initialize(NyLPC_TcTcpSocket_t* i_inst,void* i_rbuf,NyLPC_TUInt16 i_rbuf_len)
-{
-    int i;
-    NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst;
-    NyLPC_cBaseSocket_initialize(&(i_inst->_super),NyLPC_TcBaseSocket_TYPEID_TCP_SOCK);
-    //uipサービスは初期化済であること。
-    NyLPC_Assert(NyLPC_TcUipService_isInitService());
-
-    NyLPC_cFifoBuffer_initialize(&(i_inst->rxbuf),i_rbuf,i_rbuf_len);
-    //  NyLPC_AbortIfNot(NyLPC_cMutex_initialize(&(i_inst->_smutex)));//個別Mutex
-//  i_inst->_smutex=NyLPC_cIPv4_getSockMutex(&(srv->_tcpv4));//共有Mutex
-    i_inst->tcpstateflags=UIP_CLOSED;
-    i_inst->txbuf.rp=i_inst->txbuf.wp=0;
-    for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
-        i_inst->txbuf.txq[i].packet=NULL;
-    }
-    //管理リストへ登録。
-    return NyLPC_cIPv4_addSocket(&(srv->_tcpv4),&(i_inst->_super));
-}
-void NyLPC_cTcpSocket_finalize(NyLPC_TcTcpSocket_t* i_inst)
-{
-    int i;
-    NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst;
-    NyLPC_Assert(NyLPC_TcUipService_isInitService());
-    //uipサービスは初期化済であること。
-    if(!NyLPC_cIPv4_removeSocket(&(srv->_tcpv4),&(i_inst->_super))){
-        //削除失敗、それは死を意味する。
-        NyLPC_Abort();
-    }
-    //開放漏れの保険
-    if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
-        lockResource(i_inst);
-        resetTxQWithUnlock(i_inst);
-    }
-    for(i=0;i<NyLPC_TcTcpSocket_NUMBER_OF_TXQ;i++){
-        i_inst->txbuf.txq[i].packet=NULL;
-    }
-    NyLPC_cFifoBuffer_finalize(&(i_inst->rxbuf));
-//  NyLPC_cMutex_finalize(&(i_inst->_smutex));
-    NyLPC_cBaseSocket_finalize(&(i_inst->_super));
-    return;
-}
-
-
-
-NyLPC_TBool NyLPC_cTcpSocket_listenSyn(NyLPC_TcTcpSocket_t* i_inst,const struct NyLPC_TTcpSocketSynParam* i_lq,NyLPC_TUInt16 i_lport)
-{
-//  NyLPC_Assert(NyLPC_cMutex_isLocked(i_inst->_smutex));
-    lockResource(i_inst);
-    //ソケットが無効であること。
-    if(i_inst->tcpstateflags==UIP_CLOSED)
-    {
-        //localipとdefault_mmsは別枠で設定
-        /* Fill in the necessary fields for the new connection. */
-        i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_INITIAL;
-        i_inst->uip_connr.lport = i_lport;
-        i_inst->uip_connr.rport = i_lq->rport;
-        i_inst->uip_connr.ripaddr=i_lq->srcaddr;
-        i_inst->uip_connr.snd_nxt32=iss32;
-        /* rcv_nxt should be the seqno from the incoming packet + 1. */
-        i_inst->uip_connr.rcv_nxt32= i_lq->rcv_nxt32;
-        //MSSの設定
-        i_inst->uip_connr.peer_mss=(i_lq->mss!=0)?i_lq->mss:i_inst->uip_connr.default_mss;
-        i_inst->uip_connr.peer_win=0;
-        NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
-        //ここでステータスがかわる。
-        i_inst->tcpstateflags = UIP_SYN_RCVD;
-        //前回のデータが残っていた場合の保険
-        if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
-            resetTxQWithUnlock(i_inst);
-        }else{
-            unlockResource(i_inst);
-        }
-        return NyLPC_TBool_TRUE;
-    }
-    unlockResource(i_inst);
-    return NyLPC_TBool_FALSE;
-}
-
-
-/**
- * sq番のTxがキューから消え去るのを待ちます。
- * この関数は、アンロック状態でコールしてください。
- * <div>
- * パケットがキューからなくなる条件は、以下の2つです。
- * <ul>
- * <li>ACKを受信してパケットキューが更新された。</li>
- * <li>RSTを受信して(CLOSEDに遷移して)、キューがクリアされた。</li>
- * <li>送信タイムアウトで関数が(CLOSEDに遷移させて)キューをクリアした。</li>
- * </ul>
- * </div>
- * @param i_wait_msec
- * @return
- * 1番目の条件でパケットが消失したときのみ、TRUEを返します。
- * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
- */
-static NyLPC_TBool waitForTxRemove(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_sq,NyLPC_TcStopwatch_t* i_timer)
-{
-    NyLPC_TUInt8 f;
-    lockResource(i_inst);
-    do{
-        //パケットが送信中か調べる。
-        if(!isPacketAcked(i_inst,i_sq)){
-            //まだある場合は、タスクスイッチを繰り返して消失を待つ。
-            unlockResource(i_inst);
-            NyLPC_cThread_yield();
-            lockResource(i_inst);
-            continue;
-        }
-        //なくなった場合は、原因を調べる。
-        f=i_inst->tcpstateflags;
-        unlockResource(i_inst);
-        return (f==UIP_CLOSED)?NyLPC_TBool_FALSE:NyLPC_TBool_TRUE;
-    }while(!NyLPC_cStopwatch_isExpired(i_timer));
-    unlockResource(i_inst);
-    return NyLPC_TBool_FALSE;
-}
-
-
-/**
- * 再送信処理をセットして、パケットを送信します。
- * この関数は「アンロック状態で」実行してください。
- * @param i_len
- * 送信データサイズを指定します。
- * この番号は、シーケンス番号の加算値ではありませんので、注意をしてください。
- * @return
- * <ul>
- * <li>n=-1:送信キューへの投入に失敗した。</li>
- * <li>n>=0:nバイトのデータを送信キューへの投入することに成功した。</li>
- * </ul>
- * 送信キューに失敗する理由は2つあります。1つは、TXバッファがフルでタイムアウト。もうひとつは、非同期なコネクリョンのリセットです。
- * 失敗した場合、TCPステータスがCLOSEDでなければ、RSTを送信してステータスをCLOSEDにします。
- */
-static NyLPC_TInt32 sendWithRetransmit(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt8 i_tcpf,const void* i_buf,NyLPC_TUInt16 i_len,NyLPC_TcStopwatch_t* i_timer,NyLPC_TUInt32* o_ack)
-{
-    struct NyLPC_TcTcpSocket_TxQItem* txq;
-    NyLPC_TUInt16 s;
-    void* buf;
-    NyLPC_TUInt32 next_ack;
-    //送信バッファを取得
-    //@bug オブションパケット送信時に4バイト足りないメモリ要求しない?問題になってないけど。
-    for(;;){
-        buf=NyLPC_cUipService_allocTxBuf(i_len+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
-        if(buf!=NULL){
-            break;
-        }
-        //タイムアウト確認
-        if(NyLPC_cStopwatch_isExpired(i_timer)){
-            return -1;
-        }
-    };
-    lockResource(i_inst);
-    //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
-    if(i_len>0){
-        while(i_inst->uip_connr.peer_win==0){
-            unlockResource(i_inst);
-            //時間切れならエラー。
-            if(NyLPC_cStopwatch_isExpired(i_timer)){
-                return -1;
-            }
-            NyLPC_cThread_yield();
-            lockResource(i_inst);
-        }
-    }
-    //送信キューの取得
-    txq=getTxQ(i_inst,i_timer);
-    //送信キューが取れなかった。
-    if(txq==NULL){
-        //シーケンス番号をロールバックできないので、エラーとする。
-        unlockResource(i_inst);
-        NyLPC_cUipService_releaseTxBuf(buf);
-        return -1;
-    }
-
-    //送信バッファを基準とした送信サイズを計算
-    s-=SIZE_OF_IPv4_TCPIP_HEADER;
-    //送信サイズよりMMSが小さければ、送信サイズを修正
-    if(i_inst->uip_connr.peer_mss<s){
-        s=i_inst->uip_connr.peer_mss;
-    }
-    //送信サイズよりpeerのウインドウサイズが小さければ修正
-    if(i_inst->uip_connr.peer_win<s){
-        s=i_inst->uip_connr.peer_win;
-    }
-    //送信サイズより、データサイズが小さければ、送信サイズを修正
-    if(i_len<s){
-        s=i_len;
-    }
-    //ACK番号の計算
-    next_ack=i_inst->uip_connr.snd_nxt32+s+(((i_tcpf&(TCP_FIN|TCP_SYN))!=0x00)?1:0);
-    txq->rto32=i_inst->uip_connr.current_rto32;
-    txq->tick_of_sent=NyLPC_cStopwatch_now();
-
-    //パケットの書き込み
-    setTxPacket(i_inst,buf,i_tcpf,i_buf,s);
-    txq->packet=buf;
-
-    //シーケンス番号の更新
-    i_inst->uip_connr.snd_nxt32=next_ack;
-    //Peerのウインドウサイズを更新
-    i_inst->uip_connr.peer_win-=s;
-    //ACK番号の返却
-    *o_ack=txq->ackno=NyLPC_HTONL(next_ack);
-    unlockResource(i_inst);
-    NyLPC_cUipService_sendIPv4Tx(buf);
-    return s;
-}
-/**
- * RSTを1フレームだけ送信します。
- * この関数は、クローズドステータスのソケットにしてからコールします。
- * この関数は、アンロック状態でコールしてね。
- */
-static void sendRst(NyLPC_TcTcpSocket_t* i_inst)
-{
-    void* buf;
-
-    NyLPC_Assert(i_inst->tcpstateflags==UIP_CLOSED);
-    //ペイロードライタの初期化
-
-    //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。
-    buf=NyLPC_cUipService_allocSysTxBuf();
-    lockResource(i_inst);
-    i_inst->uip_connr.snd_nxt32++;
-    unlockResource(i_inst);
-    setTxPacket(i_inst,buf,TCP_RST|TCP_ACK,NULL,0);
-    NyLPC_cUipService_sendIPv4Tx(buf);
-    NyLPC_cUipService_releaseTxBuf(buf);
-    NyLPC_cIPv4Payload_finalize(&ipv4);
-    return;
-}
-
-
-
-/**
- * 受信データをバッファに書き込む。
- * 十分な空き領域がない場合、失敗する。
- * この関数は、ロックして実行してください。
- */
-static NyLPC_TBool addRecvData(NyLPC_TcTcpSocket_t* i_inst,const void* i_data,NyLPC_TUInt16 i_data_size)
-{
-    //受信データサイズを確認
-    if(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf))>=i_data_size){
-        //バッファに格納可能なら、格納。
-        NyLPC_cFifoBuffer_push(&(i_inst->rxbuf),i_data,i_data_size);
-    }else{
-        //エラー:ドロップする。
-        return NyLPC_TBool_FALSE;
-    }
-
-    return NyLPC_TBool_TRUE;
-}
-
-
-
-
-/**
- * Public function
- */
-
-NyLPC_TBool NyLPC_cTcpSocket_connect(NyLPC_TcTcpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_peer_port,NyLPC_TUInt32 i_wait_in_msec)
-{
-    volatile NyLPC_TUInt8 f;
-    NyLPC_TUInt32 sq;
-    NyLPC_TcStopwatch_t sw;
-    NyLPC_TUInt16 lport;
-    lockResource(i_inst);
-    //ソケットが無効であること。
-    if(i_inst->tcpstateflags!=UIP_CLOSED)
-    {
-        NyLPC_OnErrorGoto(Error);
-    }
-    //ポート番号の取得(lockResourceが他のソケットと共有なので、重複ポートの割当は起こりえない。でもちょっと注意して)
-    lport=NyLPC_htons(NyLPC_cIPv4_getNewPortNumber(i_inst->_super._parent_ipv4));
-    if(lport==0){
-        NyLPC_OnErrorGoto(Error);
-    }
-    //connectの為の準備
-
-    //localipとdefault_mmsは別枠で設定
-    /* Fill in the necessary fields for the new connection. */
-    i_inst->uip_connr.current_rto32 = UIP_TCP_RTO_CONNECTION_INITIAL;//RTOを短くしてARP発行時の再接続短縮を期待する。
-    i_inst->uip_connr.lport = lport;
-    i_inst->uip_connr.rport = NyLPC_htons(i_peer_port);
-    i_inst->uip_connr.ripaddr=*i_addr;
-    i_inst->uip_connr.snd_nxt32=iss32;//should be random
-    /* rcv_nxt should be the seqno from the incoming packet + 1. */
-    i_inst->uip_connr.rcv_nxt32=0;
-    //MSSの設定
-    i_inst->uip_connr.peer_mss=i_inst->uip_connr.default_mss;
-    i_inst->uip_connr.peer_win=1;//periodicの再送信を期待するために相手のWindowサイズは1と仮定する。
-    NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
-    //ここでステータスがかわる。
-    i_inst->tcpstateflags = UIP_SYN_SENT;
-    //前回のデータが残っていた場合の保険
-    if(i_inst->txbuf.rp!=i_inst->txbuf.wp){
-        resetTxQWithUnlock(i_inst);
-    }else{
-        unlockResource(i_inst);
-    }
-
-    NyLPC_cStopwatch_initialize(&sw);
-
-    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
-    if(sendWithRetransmit(i_inst,TCP_SYN,NULL,0,&sw,&sq)==0){
-        //ちょっと待つ。
-        NyLPC_cThread_yield();
-        //キューにあるTXが消えるのを待つ。
-        if(waitForTxRemove(i_inst,sq,&sw)){
-            //ACK受信に成功して、TXが消失
-            NyLPC_cStopwatch_finalize(&sw);
-            return NyLPC_TBool_TRUE;
-        }
-    }
-    //ロックして、強制的なステータス遷移
-    lockResource(i_inst);
-    f=i_inst->tcpstateflags;
-    if(f!=UIP_CLOSED){
-        //もし、強制CLOSE遷移であれば、RSTも送信。
-        i_inst->tcpstateflags=UIP_CLOSED;
-        unlockResource(i_inst);
-        sendRst(i_inst);
-    }else{
-        unlockResource(i_inst);
-    }
-    return NyLPC_TBool_FALSE;
-Error:
-    unlockResource(i_inst);
-    return NyLPC_TBool_FALSE;
-}
-
-/**
- * この関数は、UIP_SYN_RCVDステータスのソケットを、ESTABLISHEDへ遷移させます。
- * cTcpListener_listen関数を通過したインスタンスに実行してください。
- * この関数は、アプリケーションが呼び出します。
- * @return
- *
- */
-NyLPC_TBool NyLPC_cTcpSocket_accept(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
-{
-    volatile NyLPC_TUInt8 f;
-    NyLPC_TUInt32 sq;
-    NyLPC_TcStopwatch_t sw;
-
-    NyLPC_cStopwatch_initialize(&sw);
-    //ステータスチェック
-    f=i_inst->tcpstateflags;
-    switch(f)
-    {
-    case UIP_ESTABLISHED:
-        return NyLPC_TBool_TRUE;
-    case UIP_SYN_RCVD:
-        //処理対象
-        break;
-    default:
-        return NyLPC_TBool_FALSE;
-    }
-    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
-    if(sendWithRetransmit(i_inst,TCP_SYN|TCP_ACK,NULL,0,&sw,&sq)==0){
-        //ちょっと待つ。
-        NyLPC_cThread_yield();
-        //キューにあるTXが消えるのを待つ。
-        if(waitForTxRemove(i_inst,sq,&sw)){
-            //ACK受信に成功して、TXが消失
-            NyLPC_cStopwatch_finalize(&sw);
-            return NyLPC_TBool_TRUE;
-        }
-    }
-    //ロックして、強制的なステータス遷移
-    lockResource(i_inst);
-    f=i_inst->tcpstateflags;
-    if(f!=UIP_CLOSED){
-        //もし、強制CLOSE遷移であれば、RSTも送信。
-        i_inst->tcpstateflags=UIP_CLOSED;
-        unlockResource(i_inst);
-        sendRst(i_inst);
-    }else{
-        unlockResource(i_inst);
-    }
-    return NyLPC_TBool_FALSE;
-}
-
-
-/**
- * この関数は、ソケットの受信バッファの読み取り位置と、読み出せるデータサイズを返却します。
- * 関数はポインターを返却するだけで、バッファの読み取り位置をシークしません。
- * シークするにはNyLPC_cTcpSocket_pseekを使います。
- */
-NyLPC_TInt32 NyLPC_cTcpSocket_precv(NyLPC_TcTcpSocket_t* i_inst,const void** o_buf_ptr,NyLPC_TUInt32 i_wait_msec)
-{
-    volatile NyLPC_TUInt8 st;
-    NyLPC_TUInt16 rlen;
-    //タイマを生成
-    NyLPC_TcStopwatch_t sw;
-    NyLPC_cStopwatch_initialize(&sw);
-
-    //ESTABLISHED以外の場合は、エラー。
-    NyLPC_cStopwatch_setNow(&sw);
-    do{
-        //読み出しバッファ情報のコピー
-        //MUTEX LOCK
-        lockResource(i_inst);
-        st=i_inst->tcpstateflags;
-        rlen=NyLPC_cFifoBuffer_getLength(&(i_inst->rxbuf));
-        *o_buf_ptr=NyLPC_cFifoBuffer_getPtr(&(i_inst->rxbuf));
-        //MUTEX UNLOCK
-        unlockResource(i_inst);
-
-        //バッファが空の場合は、ステータスチェック。ESTABLISHEDでなければ、エラー(PASVCLOSE等の場合)
-        switch(st){
-        case UIP_ESTABLISHED:
-            if(rlen>0){
-                //バッファにパケットがあれば返却
-                NyLPC_cStopwatch_finalize(&sw);
-                return rlen;
-            }
-            break;
-        case UIP_CLOSE_WAIT:
-            if(rlen>0){
-                //バッファにパケットがあれば返却
-                NyLPC_cStopwatch_finalize(&sw);
-                return rlen;
-            }
-            //引き続きエラー処理
-        default:
-            //他の場合はエラー
-            NyLPC_cStopwatch_finalize(&sw);
-            return -1;
-        }
-        //タスクスイッチ
-        NyLPC_cThread_yield();
-    }while(NyLPC_cStopwatch_elapseInMsec(&sw)<i_wait_msec);
-    //規定時間内に受信が成功しなかった。
-    NyLPC_cStopwatch_finalize(&sw);
-    return 0;
-}
-/**
- * 受信バッファをシークします。
- * シーク後に、遅延ACKを送出します。
- */
-void NyLPC_cTcpSocket_pseek(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt16 i_seek)
-{
-    void* buf;
-    NyLPC_ArgAssert(i_seek<=NyLPC_cFifoBuffer_getLength(&(i_inst->rxbuf)));
-    if(i_seek==0){
-        return;
-    }
-
-    //ACK送信バッファの取得
-    buf=NyLPC_cUipService_allocSysTxBuf();
-
-    //MUTEX LOCK
-    lockResource(i_inst);
-
-    //受信バッファを読み出しシーク
-    NyLPC_cFifoBuffer_pop(&(i_inst->rxbuf),i_seek);
-    //ACKパケットの生成
-    setTxPacket(i_inst,buf,TCP_ACK,NULL,0);
-    unlockResource(i_inst);
-    //ACK送信
-    NyLPC_cUipService_sendIPv4Tx(buf);
-    NyLPC_cUipService_releaseTxBuf(buf);
-
-}
-
-/**
- * See header file.
- */
-void* NyLPC_cTcpSocket_allocSendBuf(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_buf_size,NyLPC_TUInt32 i_wait_in_msec)
-{
-    NyLPC_TUInt16 s;
-    void* buf;
-    NyLPC_TcStopwatch_t sw;
-
-    NyLPC_cStopwatch_initialize(&sw);
-    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
-
-    //送信バッファを取得
-    //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。
-    for(;;){
-        //ESTABLISHED以外に非同期遷移
-        if(i_inst->tcpstateflags!=UIP_ESTABLISHED){
-            NyLPC_cStopwatch_finalize(&sw);
-            return NULL;
-        }
-        buf=NyLPC_cUipService_allocTxBuf(i_hint+(SIZE_OF_IPv4_TCPIP_HEADER),&s);
-        if(buf!=NULL){
-            break;
-        }
-        //タイムアウト時もエラー
-        if(NyLPC_cStopwatch_isExpired(&sw)){
-            NyLPC_cStopwatch_finalize(&sw);
-            return NULL;
-        }
-    }
-
-//@todo 前段処理と順番を入れ替えて、要求サイズとpeerのwinのうち、小さいほうを割り当てたほうが良くない?
-//ここで相手のwin待ちをする理由は、相手に確実に受け取れるサイズを決定する為。
-    lockResource(i_inst);
-    //ペイロードがある場合のみ、相手のwindowサイズが0以上になるのを待つ。
-    while(i_inst->uip_connr.peer_win==0){
-        unlockResource(i_inst);
-        //ESTABLISHED以外に非同期遷移 orタイムアウト確認
-        if(NyLPC_cStopwatch_isExpired(&sw)||(i_inst->tcpstateflags!=UIP_ESTABLISHED)){
-            NyLPC_cUipService_releaseTxBuf(buf);
-            NyLPC_cStopwatch_finalize(&sw);
-            return NULL;
-        }
-        NyLPC_cThread_yield();
-        lockResource(i_inst);
-    }
-    //送信バッファを基準とした送信サイズを計算
-    s-=SIZE_OF_IPv4_TCPIP_HEADER;
-    //送信サイズよりMMSが小さければ、送信サイズを修正
-    if(i_inst->uip_connr.peer_mss<s){
-        s=i_inst->uip_connr.peer_mss;
-    }
-    //送信サイズよりpeerのウインドウサイズが小さければ修正
-    if(i_inst->uip_connr.peer_win<s){
-        s=i_inst->uip_connr.peer_win;
-    }
-    unlockResource(i_inst);
-    //バッファサイズ確定。
-    *o_buf_size=s;
-    NyLPC_cStopwatch_finalize(&sw);
-    return (NyLPC_TUInt8*)buf+SIZE_OF_IPv4_TCPIP_HEADER;
-}
-/**
- * See Header file.
- */
-void NyLPC_cTcpSocket_releaseSendBuf(NyLPC_TcTcpSocket_t* i_inst,void* i_buf_ptr)
-{
-    NyLPC_cUipService_releaseTxBuf((NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER);
-}
-
-
-/**
- * 事前にAllocしたTxパケットを送信します。
- * このAPIはゼロコピー送信をサポートするためのものです。
- * @param i_buf_ptr
- * allocSendBufで取得したメモリを指定します。
- * @return
- * 関数が失敗した場合、i_buf_ptrは「開放されません。」
- */
-NyLPC_TBool NyLPC_cTcpSocket_psend(NyLPC_TcTcpSocket_t* i_inst,void* i_buf_ptr,int i_len,NyLPC_TUInt32 i_wait_in_msec)
-{
-    struct NyLPC_TcTcpSocket_TxQItem* txq;
-    void* buf;
-    NyLPC_TcStopwatch_t sw;
-    //ESTABLISHEDでなければエラー
-    if(i_inst->tcpstateflags!=UIP_ESTABLISHED){
-        //ESTABLISHEDでなければエラー
-        return NyLPC_TBool_FALSE;
-    }
-    //送信データ0なら何もしない。
-    if(i_len<1){
-        NyLPC_cTcpSocket_releaseSendBuf(i_inst,i_buf_ptr);
-        return NyLPC_TBool_TRUE;
-    }
-    NyLPC_cStopwatch_initialize(&sw);
-    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
-
-    //先頭ポインタは、i_buf-sizeof(SIZE_OF_IPv4_TCPIP_HEADER)固定
-    buf=(NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_TCPIP_HEADER;
-    lockResource(i_inst);
-    //送信キューの取得
-    txq=getTxQ(i_inst,&sw);
-    //送信キューが取れなかった。
-    if(txq==NULL){
-        //シーケンス番号をロールバックできないので、エラーとする。
-        unlockResource(i_inst);
-        NyLPC_cStopwatch_finalize(&sw);
-        return NyLPC_TBool_FALSE;
-    }
-    //ここから先はi_bufの所有権はインスタンスになってる。
-
-    //IPv4ペイロードの書き込み
-
-    //allocをした時点でwin,mssは考慮されているので、そのままそうしんしる。
-
-    //ACK番号の計算
-    txq->rto32=i_inst->uip_connr.current_rto32;
-    txq->tick_of_sent=NyLPC_cStopwatch_now();
-    //パケットヘッダの生成(ヘッダ長はpreadで定義した値(4+6)*4=40です。)
-    setTxPacketHeader(i_inst,buf,TCP_ACK|TCP_PSH,i_len);
-    txq->packet=buf;
-
-    //シーケンス番号の更新
-    i_inst->uip_connr.snd_nxt32=i_inst->uip_connr.snd_nxt32+i_len;
-    //Peerのウインドウサイズを更新
-    i_inst->uip_connr.peer_win-=i_len;
-    //ACK番号の返却
-    txq->ackno=NyLPC_HTONL(i_inst->uip_connr.snd_nxt32);
-    unlockResource(i_inst);
-    NyLPC_cUipService_sendIPv4Tx(buf);
-    NyLPC_cStopwatch_finalize(&sw);
-    return NyLPC_TBool_TRUE;
-}
-
-/**
- * See header file.
- */
-NyLPC_TInt32 NyLPC_cTcpSocket_send(NyLPC_TcTcpSocket_t* i_inst,const void* i_buf_ptr,NyLPC_TInt32 i_len,NyLPC_TUInt32 i_wait_in_msec)
-{
-    NyLPC_TInt16 hint;
-    NyLPC_TUInt16 s;
-    void* buf;
-    if(i_len<1){
-        return 0;
-    }
-    hint=(i_len>32767)?32767:i_len;
-    buf=NyLPC_cTcpSocket_allocSendBuf(i_inst,hint,&s,i_wait_in_msec);
-    if(buf==NULL){
-        return -1;
-    }
-    //送信サイズの計算
-    s=((NyLPC_TInt32)s<i_len)?s:(NyLPC_TUInt16)i_len;
-    memcpy(buf,i_buf_ptr,s);
-    if(!NyLPC_cTcpSocket_psend(i_inst,buf,s,i_wait_in_msec)){
-        NyLPC_cTcpSocket_releaseSendBuf(i_inst,buf);
-        return -1;//error
-    }
-    return s;
-}
-
-
-void NyLPC_cTcpSocket_close(NyLPC_TcTcpSocket_t* i_inst,NyLPC_TUInt32 i_wait_in_msec)
-{
-    NyLPC_TcStopwatch_t sw;
-    volatile NyLPC_TUInt8 f;
-    NyLPC_TUInt32 sq;
-    NyLPC_cStopwatch_initialize(&sw);
-    NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec);
-    lockResource(i_inst);
-
-    f=i_inst->tcpstateflags;
-    //ステータスチェック
-    switch(f)
-    {
-    case UIP_CLOSED:
-        //閉じている。
-        goto ReturnWithUnlock;
-    case UIP_ESTABLISHED:
-        //アクティブクローズ。
-        i_inst->tcpstateflags=UIP_FIN_WAIT_1;
-        //送信のために一旦解除
-        unlockResource(i_inst);
-        //FINの送信
-        if(sendWithRetransmit(i_inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
-            //ちょっと待つ。
-            NyLPC_cThread_yield();
-            //TXの消去待ち
-            if(waitForTxRemove(i_inst,sq,&sw)){
-                //再ロック
-                lockResource(i_inst);
-                //タイムアウトするか、UIP_CLOSED、もしくはTIME_WAITに遷移するのを待つ。(遷移はRxprocで自動的に実行。)
-                do{
-                    switch(i_inst->tcpstateflags)
-                    {
-                    case UIP_TIME_WAIT:
-                        i_inst->tcpstateflags=UIP_CLOSED;
-                    case UIP_CLOSED:
-                        NyLPC_Assert(i_inst->txbuf.rp==i_inst->txbuf.wp);
-                        //成功。
-                        goto ReturnWithUnlock;
-                    case UIP_FIN_WAIT_1:
-                    case UIP_FIN_WAIT_2:
-                    case UIP_CLOSING:
-                        //一時的なアンロック
-                        unlockResource(i_inst);
-                        NyLPC_cThread_yield();
-                        lockResource(i_inst);
-                    default:
-                        break;
-                    }
-                }while(!NyLPC_cStopwatch_isExpired(&sw));
-                unlockResource(i_inst);
-            }
-        }
-        break;
-    case UIP_CLOSE_WAIT:
-        //LAST_ACKへ遷移
-        i_inst->tcpstateflags=UIP_LAST_ACK;
-        //送信のために一旦解除
-        unlockResource(i_inst);
-        if(sendWithRetransmit(i_inst,TCP_FIN|TCP_ACK,NULL,0,&sw,&sq)==0){
-            //ちょっと待つ。
-            NyLPC_cThread_yield();
-            //TXの消去待ち
-            if(waitForTxRemove(i_inst,sq,&sw)){
-                //再ロック
-                lockResource(i_inst);
-                //TX消去後にCLOSEDに遷移していればOK
-                if(i_inst->tcpstateflags==UIP_CLOSED)
-                {
-                    NyLPC_Assert(i_inst->txbuf.rp==i_inst->txbuf.wp);
-                    goto ReturnWithUnlock;
-                }
-                unlockResource(i_inst);
-            }
-        }
-        //エラー。RSTで切断。
-        break;
-    default:
-        unlockResource(i_inst);
-        NyLPC_Warning();
-        break;
-    }
-//  if(i_inst->_smutex._lock_count>0){
-//      NyLPC_Warning();
-//  }
-    //このパスに到達するのは、FIN送信/ACKに成功したにも拘らず、規定時間内にCLOSEDに遷移しなかった場合。
-    //コネクションを強制遷移して、RST
-    lockResource(i_inst);
-    f=i_inst->tcpstateflags;
-    if(f!=UIP_CLOSED){
-        //もし、強制CLOSE遷移であれば、RSTも送信。
-        i_inst->tcpstateflags=UIP_CLOSED;
-        unlockResource(i_inst);
-        sendRst(i_inst);
-    }else{
-        unlockResource(i_inst);
-    }
-    NyLPC_cStopwatch_finalize(&sw);
-    return;
-ReturnWithUnlock:
-    unlockResource(i_inst);
-    NyLPC_cStopwatch_finalize(&sw);
-    return;
-}
-
-/**
- * uipサービスタスクが実行する関数です。
- * 定期的に実行する関数。最低でも1s単位で実行してください。
- */
-void NyLPC_cTcpSocket_periodic(
-    NyLPC_TcTcpSocket_t* i_inst)
-{
-    int i;
-    struct NyLPC_TcTcpSocket_TxQItem* q=i_inst->txbuf.txq;
-    NyLPC_TcStopwatch_t sw;
-    NyLPC_TUInt32 now;
-    int rp;
-    NyLPC_cStopwatch_initialize(&sw);
-    now=NyLPC_cStopwatch_now();
-    //MUTEX LOCK
-    lockResource(i_inst);
-    if(i_inst->tcpstateflags==UIP_CLOSED)
-    {
-        //CLOSEDなら、バッファ開放。
-        resetTxQWithUnlock(i_inst);
-    }else if(i_inst->txbuf.rp==i_inst->txbuf.wp){
-        //再送信パケットがなければ何もしないよ。
-        unlockResource(i_inst);
-    }else if(i_inst->uip_connr.peer_win==0){
-        //peer_winが0の場合は何もしない。
-        unlockResource(i_inst);
-    }else{
-        //再送信処理
-        rp=i_inst->txbuf.rp;
-        NyLPC_cStopwatch_set(&sw,q[rp].tick_of_sent);
-        if(NyLPC_cStopwatch_elapseInMsec(&sw)>q[rp].rto32){
-            //最古のパケットの送信時間をチェックして、タイムアウトが発生したら、再送時間と送信時刻をセット
-            //最古パケットRTOを2倍。
-            q[rp].rto32*=2;
-            for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
-                q[i].tick_of_sent=now;
-            }
-            if(q[rp].rto32>UIP_IP_RTO_MAX_RTO){
-                //最古のRTOが64秒を超えたら、CLOSED
-                i_inst->tcpstateflags =UIP_CLOSED;
-                resetTxQWithUnlock(i_inst);
-                sendRst(i_inst);
-            }else{
-                //規定時間内なら、再送処理
-                for(i=rp;i!=i_inst->txbuf.wp;i=(i+1)%NyLPC_TcTcpSocket_NUMBER_OF_TXQ){
-//                  NyLPC_cUipService_sendIPv4Tx(NyLPC_cIPv4Payload_getBuf(&(q[i].data)));
-                    NyLPC_cUipService_sendIPv4Tx(q[i].packet);
-                }
-                unlockResource(i_inst);
-            }
-        }else{
-            unlockResource(i_inst);
-        }
-    }
-    NyLPC_cStopwatch_finalize(&sw);
-    return;
-}
-/**
- * uipサービスタスクが実行する関数です。
- * サービスの開始を通知します。
- */
-void NyLPC_cTcpSocket_startService(NyLPC_TcTcpSocket_t* i_inst,const NyLPC_TcIPv4Config_t* i_config)
-{
-    NyLPC_Assert(i_inst->tcpstateflags==UIP_CLOSED);//閉じてなければおかしい。
-    i_inst->uip_connr.lipaddr=&(i_config->ip_addr);
-    i_inst->uip_connr.default_mss=i_config->default_mss;
-    //NyLPC_cTcpSocket_setSynPayload関数でも実行するけど、IFのリセット時なのでここでもやる。
-    NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf));
-    return;
-}
-/**
- * uipサービスタスクが実行する関数です。
- * サービスの停止を通知します。
- */
-void NyLPC_cTcpSocket_stopService(NyLPC_TcTcpSocket_t* i_inst)
-{
-    lockResource(i_inst);
-    if(i_inst->tcpstateflags==UIP_CLOSED)
-    {
-        unlockResource(i_inst);
-    }else{
-        i_inst->tcpstateflags=UIP_CLOSED;
-        resetTxQWithUnlock(i_inst);
-        sendRst(i_inst);
-    }
-    return;
-}
-
-
-void* NyLPC_cTcpSocket_parseRx(
-    NyLPC_TcTcpSocket_t* i_inst,
-    const NyLPC_TcIPv4Payload_t* i_ipp)
-{
-    int i,s;
-    NyLPC_TUInt16 tmp16;
-    NyLPC_TUInt16 data_size;
-    NyLPC_TUInt8 in_tcpflag=i_ipp->payload.tcp->flags;
-    const void* tcp_data_offset;
-    NyLPC_TBool is_new_packet;
-    int num_of_noack;
-    void* dlist[NyLPC_TcTcpSocket_NUMBER_OF_TXQ];
-    void* ret;
-
-    //パラメータの計算
-
-    tmp16=NyLPC_TTcpHeader_getHeaderLength(i_ipp->payload.tcp);
-    //TCPペイロードの長さは、IPパケットの長さ-(IPヘッダ+TCPヘッダ)
-    data_size=NyLPC_TIPv4Header_getPacketLength(i_ipp->header)-NyLPC_TIPv4Header_getHeaderLength(i_ipp->header)-tmp16;
-    //TCPデータオフセット
-    tcp_data_offset=i_ipp->payload.rawbuf+tmp16;
-
-    //インスタンスをロックする。
-    lockResource(i_inst);
-
-    //RSTのチェック。RST受信時は、状態にかかわらず、CLOSEDステータスに移行する。
-    if (in_tcpflag & TCP_RST)
-    {
-        i_inst->tcpstateflags =UIP_CLOSED;
-        goto DROP;
-    }
-
-
-    is_new_packet=NyLPC_ntohl(i_ipp->payload.tcp->seqno32)==i_inst->uip_connr.rcv_nxt32;
-
-
-    //OPTIONの反映
-
-    //MSSの取得
-    if(NyLPC_TTcpHeader_getTcpMmsOpt(i_ipp->payload.tcp,&tmp16)){
-        //取得で着たら更新
-        i_inst->uip_connr.peer_mss=tmp16;
-    }
-    //受信パケットを元に、未ACKパケットの数を計算
-    num_of_noack=getNumOfSending(i_inst,i_ipp->payload.tcp->ackno32);//i_inst->txbuf.num_of_txq;
-
-    //ステータス毎のACK応答
-    switch(i_inst->tcpstateflags)
-    {
-    case UIP_SYN_RCVD:
-        //ACKを受信したら、ESTABLISHEDへ。
-        //すべてのパケットをACKしたかで判定。()
-        if(num_of_noack==0){
-            i_inst->tcpstateflags=UIP_ESTABLISHED;
-        }else{
-            //それ以外のパケットはドロップする。
-            break;//goto DROP;
-        }
-        //新しいパケットがなければ、無応答
-        if(!is_new_packet){
-            break;//goto DROP;
-        }
-        //引き続き、ESTABLISHEDの処理へ。
-    case UIP_ESTABLISHED:
-        if(data_size>0){
-            if(is_new_packet){
-                if(addRecvData(i_inst,tcp_data_offset,data_size)){
-                    //通常のACK返却
-                    i_inst->uip_connr.rcv_nxt32+=data_size;
-                }else{
-                    //失敗したときは必要に応じて単純ACK
-                }
-            }
-        }
-        //どちらにしろ、ACK送信
-        if(is_new_packet && (in_tcpflag & TCP_FIN)){
-            //FINがあるときは、ステータスをCLOSE_WAITへセットして、ACKを返す。
-            i_inst->tcpstateflags = UIP_CLOSE_WAIT;
-            i_inst->uip_connr.rcv_nxt32++;
-        }
-        break;
-    case UIP_CLOSE_WAIT:
-        //必要に応じたACK応答
-        break;
-    case UIP_LAST_ACK:
-        //ACK(by FIN)が得られたなら、CLOSEDへ。
-        if(num_of_noack==0){
-            i_inst->tcpstateflags=UIP_CLOSED;
-        }
-        //必要に応じたACK応答
-        break;
-    case UIP_FIN_WAIT_1:
-        //FIN受信->CLOSINGへ
-        if(is_new_packet){
-            i_inst->uip_connr.rcv_nxt32+=data_size;
-            if(in_tcpflag & TCP_FIN){
-                i_inst->uip_connr.rcv_nxt32++;
-                if(num_of_noack==0){
-                    //FINとACKを受信
-                    i_inst->tcpstateflags=UIP_TIME_WAIT;
-                }else{
-                    //FINのみ
-                    i_inst->tcpstateflags=UIP_CLOSING;
-                }
-            }
-        }else if(num_of_noack==0){
-            //ACKのみ
-            i_inst->tcpstateflags=UIP_FIN_WAIT_2;
-        }
-        //必要に応じたACK応答
-        break;
-    case UIP_FIN_WAIT_2:
-        //FIN受信->TIME_WAITへ(pureACK)
-        if(is_new_packet && (in_tcpflag & TCP_FIN)){
-            i_inst->uip_connr.rcv_nxt32++;
-            i_inst->tcpstateflags=UIP_TIME_WAIT;
-        }
-        break;
-    case UIP_CLOSING:
-        //ACK受信したら、TIME_WAITへ
-        if(num_of_noack==0){
-            i_inst->tcpstateflags=UIP_TIME_WAIT;
-        }
-        break;
-    case UIP_CLOSED:
-        //何もできない。何もしない。
-        break;
-    case UIP_TIME_WAIT:
-        //最終ACKを送り続ける。
-        break;
-    case UIP_SYN_SENT:
-        //connect関数実行中しか起動しないステータス
-        if(num_of_noack==0){
-            i_inst->tcpstateflags=UIP_ESTABLISHED;
-            i_inst->uip_connr.rcv_nxt32=NyLPC_ntohl(i_ipp->payload.tcp->seqno32)+1;
-        }else{
-            //それ以外のパケットはドロップする。
-            break;//goto DROP;
-        }
-        //ACKを送る。
-        break;
-    default:
-        goto DROP;
-    }
-    //ウインドウサイズを更新
-    i_inst->uip_connr.peer_win=NyLPC_ntohs(i_ipp->payload.tcp->wnd16);
-
-    //送信キューから、Peerが受信したデータを削除する。
-    if(in_tcpflag & TCP_ACK){
-        //再送パケットキューから送信済みのデータを回収(後で開放)
-        NyLPC_Trace();
-        s=updateTxQByIndex(i_inst,i_ipp->payload.tcp->ackno32,dlist);
-        NyLPC_Trace();
-    }else{
-        s=0;
-    }
-    //新しいパケットがきた場合は、再送キューのACKを更新する。
-    if(is_new_packet){
-        //再送キューのACKを更新
-        updateTxAck(i_inst,NyLPC_htonl(i_inst->uip_connr.rcv_nxt32));
-    }
-
-    //送信キューのない
-    if(((in_tcpflag&(TCP_FIN|TCP_SYN))!=0x00) ||
-        ((!is_new_packet) && (data_size>0)))
-    {
-        //ソケットからPureACKを生成 as setPacket(i_inst,i_ipp,TCP_ACK,NULL,0);
-        ret=NyLPC_cUipService_allocSysTxBuf();
-        setTxPacket(i_inst,ret,TCP_ACK,NULL,0);
-    }else{
-        ret=NULL;
-    }
-    unlockResource(i_inst);
-    //取り外したTXメモリの開放
-    for(i=0;i<s;i++){
-        //取り外したTXメモリを開放
-        NyLPC_cUipService_releaseTxBuf(dlist[i]);
-    }
-NyLPC_Trace();
-    return ret;
-DROP:
-    //ACKしたパケットを送信キューから削除
-    unlockResource(i_inst);
-NyLPC_Trace();
-    return NULL;
-}
-
-
-/**
- * 入力されたパケットからRSTパケットを生成して返す。
- */
-void* NyLPC_cTcpSocket_allocTcpReverseRstAck(
-    const NyLPC_TcIPv4Payload_t* i_src)
-{
-    struct NyLPC_TIPv4Header*   iph;
-    struct NyLPC_TTcpHeader*    tcph;
-    NyLPC_TUInt8 iph_word=0x05;
-    NyLPC_TUInt8 tcph_word=(UIP_TCPH_LEN) / 4;
-    void* txb=NyLPC_cUipService_allocSysTxBuf();
-    //IPヘッダの更新
-    iph=(struct NyLPC_TIPv4Header*)txb;
-    iph->vhl=0x40|(0x0f&iph_word);
-    iph->destipaddr=i_src->header->srcipaddr;
-    iph->srcipaddr =i_src->header->destipaddr;
-    NyLPC_TIPv4Header_writeTxIpHeader(iph,UIP_PROTO_TCP);
-
-    //TCPヘッダの更新
-    tcph=(struct NyLPC_TTcpHeader*)(((NyLPC_TUInt8*)txb)+NyLPC_TIPv4Header_getHeaderLength(iph));
-
-    tcph->tcpoffset=(tcph_word<<4);
-
-    tcph->flags    = TCP_RST | TCP_ACK;
-    //sorce & destination port
-    tcph->srcport  = i_src->payload.tcp->destport;
-    tcph->destport = i_src->payload.tcp->srcport;
-    //ACK number
-    tcph->ackno32  = NyLPC_htonl(NyLPC_ntohl(i_src->payload.tcp->seqno32)+1);
-    //Seq Number
-    tcph->seqno32  = i_src->payload.tcp->ackno32;
-    //uip_func_tcp_send_noconn(BUF);
-    tcph->urgp[0]  = tcph->urgp[1] = 0;
-    tcph->tcpchksum= 0;
-
-
-    //最終的なパケットサイズと必要ならペイロードを書き込み
-    iph->len16=NyLPC_htons((iph_word+tcph_word)*4);
-    //WND設定
-    tcph->wnd16=0;
-    //Checksumの生成
-    tcph->tcpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(iph));
-    iph->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(iph));
-    return txb;
-}
-
-
-
-