OSDN Git Service

add mbed.html
[mimic/MiMicSDK.git] / lib / src / uip / NyLPC_cTcpListener.c
1 /*********************************************************************************\r
2  * PROJECT: MiMic\r
3  * --------------------------------------------------------------------------------\r
4  *\r
5  * This file is part of MiMic\r
6  * Copyright (C)2011 Ryo Iizuka\r
7  *\r
8  * MiMic is free software: you can redistribute it and/or modify\r
9  * it under the terms of the GNU Lesser General Public License as published\r
10  * by the Free Software Foundation, either version 3 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU Lesser General Public License\r
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
20  *\r
21  * For further information please contact.\r
22  *      http://nyatla.jp/\r
23  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
24  *\r
25  *********************************************************************************/\r
26 #include "NyLPC_cTcpListener_protected.h"\r
27 #include "NyLPC_cTcpSocket_protected.h"\r
28 #include "NyLPC_cUipService_protected.h"\r
29 #include "NyLPC_cIPv4.h"\r
30 #include "NyLPC_stdlib.h"\r
31 #include <stdio.h>\r
32 /**\r
33  * NyLPC_TTcpListenerListenQ\r
34  */\r
35 \r
36 void NyLPC_TTcpListenerListenQ_init(struct NyLPC_TTcpListenerListenQ* i_struct)\r
37 {\r
38         i_struct->wp=0;\r
39         int i;\r
40         for(i=NyLPC_TcTcpListener_NUMBER_OF_Q-1;i>=0;i--){\r
41                 i_struct->item[i].rport=0;\r
42         }\r
43 }\r
44 \r
45 /**\r
46  * ListenQへSYNパケットの情報を追加する。\r
47  */\r
48 void NyLPC_TTcpListenerListenQ_add(struct NyLPC_TTcpListenerListenQ* i_struct,const NyLPC_TcIPv4Payload_t* i_payload)\r
49 {\r
50         struct NyLPC_TTcpSocketSynParam* item=&i_struct->item[i_struct->wp];\r
51         //未処理のものがあれば登録しない。\r
52         if(item->rport!=0){\r
53                 return;\r
54         }\r
55 \r
56         //SYNリングバッファにセット\r
57         item->rport = i_payload->payload.tcp->srcport;\r
58         item->srcaddr=i_payload->header->srcipaddr;\r
59         item->rcv_nxt32=NyLPC_ntohl(i_payload->payload.tcp->seqno32)+1;\r
60         //MSSの設定\r
61         if(!NyLPC_TTcpHeader_getTcpMmsOpt(i_payload->payload.tcp,&item->mss)){\r
62                 item->mss=0;\r
63         }\r
64         //書込み位置の進行\r
65         i_struct->wp=(i_struct->wp+1)%NyLPC_TcTcpListener_NUMBER_OF_Q;\r
66 }\r
67 \r
68 /**\r
69  * 最も古いSYNパケット情報のインデクスをキューから返す。\r
70  * @return\r
71  * 見つからない場合-1である。\r
72  */\r
73 int NyLPC_TTcpListenerListenQ_getLastIndex(struct NyLPC_TTcpListenerListenQ* i_struct)\r
74 {\r
75         int i,t;\r
76         //古いものから順に返す\r
77         for(i=1;i<=NyLPC_TcTcpListener_NUMBER_OF_Q;i++){\r
78                 t=(i_struct->wp+i)%NyLPC_TcTcpListener_NUMBER_OF_Q;\r
79                 //有効なデータ?\r
80                 if(i_struct->item[t].rport!=0){\r
81                         return t;\r
82                 }\r
83         }\r
84         return -1;\r
85 }\r
86 \r
87 /**\r
88  * ListenQのN番目を削除する。\r
89  */\r
90 void NyLPC_TTcpListenerListenQ_remove(struct NyLPC_TTcpListenerListenQ* i_struct,int i_idx)\r
91 {\r
92         i_struct->item[i_idx].rport=0;\r
93         return;\r
94 }\r
95 \r
96 \r
97 \r
98 \r
99 \r
100 \r
101 //#define lockResource(i_inst) NyLPC_cMutex_lock(((i_inst)->_mutex))\r
102 //#define unlockResource(i_inst) NyLPC_cMutex_unlock(((i_inst)->_mutex))\r
103 #define lockResource(i_inst) NyLPC_cMutex_lock(NyLPC_cIPv4_getListenerMutex(((i_inst)->_super._parent_ipv4)))\r
104 #define unlockResource(i_inst) NyLPC_cMutex_unlock(NyLPC_cIPv4_getListenerMutex(((i_inst)->_super._parent_ipv4)))\r
105 \r
106 \r
107 /**\r
108  * uipサービスが稼働中にのみ機能します。
109  */\r
110 NyLPC_TBool NyLPC_cTcpListener_initialize(NyLPC_TcTcpListener_t* i_inst,NyLPC_TUInt16 i_port)\r
111 {\r
112         NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst;\r
113         NyLPC_cBaseSocket_initialize(&(i_inst->_super),NyLPC_TcBaseSocket_TYPEID_TCP_LISTENER);\r
114         NyLPC_TTcpListenerListenQ_init(&i_inst->_listen_q);\r
115         //uipサービスは初期化済であること。\r
116         NyLPC_Assert(NyLPC_TcUipService_isInitService());\r
117         //初期化\r
118 //      //      NyLPC_cMutex_initialize(&(i_inst->_mutex));\r
119 //      i_inst->_mutex=NyLPC_cIPv4_getListenerMutex(&srv->_tcpv4);//    NyLPC_cMutex_initialize(&(i_inst->_mutex));\r
120         i_inst->_port=NyLPC_htons(i_port);\r
121         //管理リストへ登録。\r
122         return NyLPC_cIPv4_addSocket(&(srv->_tcpv4),&(i_inst->_super));\r
123 }\r
124 \r
125 void NyLPC_cTcpListener_finaize(NyLPC_TcTcpListener_t* i_inst)\r
126 {\r
127         NyLPC_TcUipService_t* srv=_NyLPC_TcUipService_inst;\r
128         NyLPC_Assert(NyLPC_TcUipService_isInitService());\r
129         //uipサービスは初期化済であること。\r
130         if(!NyLPC_cIPv4_removeSocket(&(srv->_tcpv4),&(i_inst->_super))){\r
131                 //削除失敗、それは死を意味する。\r
132                 NyLPC_Abort();\r
133         }\r
134         NyLPC_cBaseSocket_finalize(&(i_inst->_super));\r
135         return;\r
136 }\r
137 \r
138 \r
139 \r
140 \r
141 NyLPC_TBool NyLPC_cTcpListener_listen(NyLPC_TcTcpListener_t* i_inst,NyLPC_TcTcpSocket_t* i_sock,NyLPC_TUInt32 i_wait_msec)\r
142 {\r
143         int qi;\r
144         NyLPC_TcStopwatch_t sw;\r
145         NyLPC_TBool ret=NyLPC_TBool_FALSE;\r
146         //サービスは稼働中であること。\r
147         NyLPC_Assert(NyLPC_cUipService_isRun());\r
148 \r
149         //入力ソケットはCLOSEDであること。\r
150         if(i_sock->tcpstateflags!=UIP_CLOSED){\r
151                 return NyLPC_TBool_FALSE;\r
152         }\r
153 \r
154         //ストップウォッチを起動\r
155         NyLPC_cStopwatch_initialize(&sw);\r
156         NyLPC_cStopwatch_setNow(&sw);\r
157 \r
158 \r
159         //Listenerのリソースロック\r
160         lockResource(i_inst);\r
161 \r
162         while(NyLPC_cStopwatch_elapseInMsec(&sw)<i_wait_msec){\r
163                 qi=NyLPC_TTcpListenerListenQ_getLastIndex(&i_inst->_listen_q);\r
164                 if(qi>=0){\r
165                         //SYN処理要求がある\r
166                         if(!NyLPC_cTcpSocket_listenSyn(i_sock,&i_inst->_listen_q.item[qi],i_inst->_port)){\r
167                                 ret=NyLPC_TBool_FALSE;\r
168                         }else{\r
169                                 //成功\r
170                                 ret=NyLPC_TBool_TRUE;\r
171                         }\r
172                         //処理したSYNの削除\r
173                         NyLPC_TTcpListenerListenQ_remove(&i_inst->_listen_q,qi);\r
174                         break;\r
175                 }else{\r
176                         //SYN処理要求は無い(しばらくまつ)\r
177                         unlockResource(i_inst);\r
178                         NyLPC_cThread_yield();\r
179                         lockResource(i_inst);\r
180                 }\r
181         }\r
182         //タイムアウト\r
183         unlockResource(i_inst);\r
184         NyLPC_cStopwatch_finalize(&sw);\r
185         return ret;\r
186 }\r
187 \r
188 /**\r
189  * この関数は、Uip受信タスクから実行します。
190  */\r
191 NyLPC_TBool NyLPC_cTcpListener_synPacket(NyLPC_TcTcpListener_t* i_inst,const NyLPC_TcIPv4Payload_t* i_payload)\r
192 {\r
193         //パケットチェック。SYN設定されてる?\r
194         if(!(i_payload->payload.tcp->flags & TCP_SYN)){\r
195                 //SYNない\r
196                 return NyLPC_TBool_FALSE;\r
197         }\r
198         //peer port==0は受け取らない。\r
199         if(i_payload->payload.tcp->srcport==0){\r
200                 return NyLPC_TBool_FALSE;\r
201         }\r
202         //Listenerのリソースロック\r
203         lockResource(i_inst);\r
204         //ListenQへ追加\r
205         NyLPC_TTcpListenerListenQ_add(&(i_inst->_listen_q),i_payload);\r
206         //Listenerのリソースアンロック\r
207         unlockResource(i_inst);\r
208         return NyLPC_TBool_TRUE;\r
209 }\r
210 \r
211 \r
212 \r
213 \r