This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
NyLPC_cMiMicIpUdpSocket.c
00001 /********************************************************************************* 00002 * PROJECT: MiMic 00003 * -------------------------------------------------------------------------------- 00004 * 00005 * This file is part of MiMic 00006 * Copyright (C)2011 Ryo Iizuka 00007 * 00008 * MiMic is free software: you can redistribute it and/or modify 00009 * it under the terms of the GNU Lesser General Public License as published 00010 * by the Free Software Foundation, either version 3 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public License 00019 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00020 * 00021 * For further information please contact. 00022 * http://nyatla.jp/ 00023 * <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp> 00024 * 00025 * 00026 * Parts of this file were leveraged from uIP: 00027 * 00028 * Copyright (c) 2001-2003, Adam Dunkels. 00029 * All rights reserved. 00030 * 00031 * Redistribution and use in source and binary forms, with or without 00032 * modification, are permitted provided that the following conditions 00033 * are met: 00034 * 1. Redistributions of source code must retain the above copyright 00035 * notice, this list of conditions and the following disclaimer. 00036 * 2. Redistributions in binary form must reproduce the above copyright 00037 * notice, this list of conditions and the following disclaimer in the 00038 * documentation and/or other materials provided with the distribution. 00039 * 3. The name of the author may not be used to endorse or promote 00040 * products derived from this software without specific prior 00041 * written permission. 00042 * 00043 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00044 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00045 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00046 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00047 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00048 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00049 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00050 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00051 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00052 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00053 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00054 */ 00055 #include "NyLPC_cMiMicIpUdpSocket_protected.h" 00056 #include "NyLPC_cIPv4Payload_protected.h" 00057 #include "NyLPC_cMiMicIpNetIf_protected.h" 00058 00059 /** 00060 * フラグ値 00061 */ 00062 #define NyLPC_cMiMicIpUdpSocket_FLAG_BROADCAST 0 00063 /** 00064 * UDP/IPヘッダのサイズ 00065 */ 00066 #define SIZE_OF_IPv4_UDPIP_HEADER 28 00067 00068 #define lockResource(i_inst) NyLPC_cMutex_lock(((i_inst)->_smutex)) 00069 #define unlockResource(i_inst) NyLPC_cMutex_unlock(((i_inst)->_smutex)) 00070 00071 /* 00072 * 関数テーブル 00073 */ 00074 static void joinMulticast(NyLPC_TiUdpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr); 00075 static void setBroadcast(NyLPC_TiUdpSocket_t* i_inst); 00076 static NyLPC_TInt32 precv(NyLPC_TiUdpSocket_t* i_inst,const void** o_buf_ptr,const struct NyLPC_TIPv4RxInfo** o_info,NyLPC_TUInt32 i_wait_msec); 00077 static void pseek(NyLPC_TiUdpSocket_t* i_inst); 00078 static void* allocSendBuf(NyLPC_TiUdpSocket_t* i_inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_buf_size,NyLPC_TUInt32 i_wait_in_msec); 00079 static void releaseSendBuf(NyLPC_TiUdpSocket_t* i_inst,void* i_buf_ptr); 00080 static NyLPC_TBool psend(NyLPC_TiUdpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_port,void* i_buf_ptr,int i_len); 00081 static NyLPC_TInt32 send(NyLPC_TiUdpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_port,const void* i_buf_ptr,NyLPC_TInt32 i_len,NyLPC_TUInt32 i_wait_in_msec); 00082 static void setOnRxHandler(NyLPC_TiUdpSocket_t* i_inst,NyLPC_TiUdpSocket_onRxHandler i_handler); 00083 static void setOnPeriodicHandler(NyLPC_TiUdpSocket_t* i_inst,NyLPC_TiUdpSocket_onPeriodicHandler i_handler); 00084 static const struct NyLPC_TIPv4Addr* getSockIP(const NyLPC_TiUdpSocket_t* i_inst); 00085 static void finalize(NyLPC_TiUdpSocket_t* i_inst); 00086 00087 static const struct NyLPC_TiUdpSocket_Interface interface= 00088 { 00089 joinMulticast, 00090 setBroadcast, 00091 precv, 00092 pseek, 00093 allocSendBuf, 00094 releaseSendBuf, 00095 psend, 00096 send, 00097 setOnRxHandler, 00098 setOnPeriodicHandler, 00099 getSockIP, 00100 finalize 00101 }; 00102 00103 00104 00105 00106 /* 00107 * Initializer/Finalizer 00108 */ 00109 00110 00111 NyLPC_TBool NyLPC_cMiMicIpUdpSocket_initialize(NyLPC_TcMiMicIpUdpSocket_t* i_inst,NyLPC_TUInt16 i_port,void* i_rbuf,NyLPC_TUInt16 i_rbuf_len) 00112 { 00113 NyLPC_TcMiMicIpNetIf_t* srv=_NyLPC_TcMiMicIpNetIf_inst; 00114 i_inst->_super._interface=&interface; 00115 i_inst->_super._tag=NULL; 00116 //uipサービスは初期化済であること。 00117 NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService()); 00118 i_inst->_smutex=NyLPC_cIPv4_getSockMutex(&(srv->_tcpv4)); 00119 i_inst->uip_udp_conn.lport=NyLPC_htons(i_port); 00120 i_inst->uip_udp_conn.mcastaddr=NyLPC_TIPv4Addr_ZERO; 00121 i_inst->uip_udp_conn.flags=0x00; 00122 i_inst->as_handler.rx=NULL; 00123 i_inst->as_handler.periodic=NULL; 00124 00125 NyLPC_cFifoBuffer_initialize(&(i_inst->rxbuf),i_rbuf,i_rbuf_len); 00126 //管理リストへ登録。 00127 return NyLPC_TBool_TRUE; 00128 } 00129 00130 00131 00132 /** 00133 * IP+UDPヘッダサイズを0x05*4+8バイトとして、UDPの送信バッファをセットします。 00134 */ 00135 static void setUdpTxBufHeader(const NyLPC_TcMiMicIpUdpSocket_t* i_inst,void*i_buf,const struct NyLPC_TIPv4Addr* i_dest_ip,NyLPC_TUInt16 i_dest_port,NyLPC_TUInt8 i_iph_word,NyLPC_TUInt16 i_payload_size) 00136 { 00137 struct NyLPC_TIPv4Header* header=(struct NyLPC_TIPv4Header*)i_buf; 00138 struct NyLPC_TUdpHeader* udp =(struct NyLPC_TUdpHeader*)(((NyLPC_TUInt8*)i_buf)+i_iph_word*4); 00139 00140 header->vhl=0x40|(0x0f&i_iph_word); 00141 header->len16=NyLPC_htons(i_payload_size+(i_iph_word*4+8)); 00142 udp->udplen=NyLPC_htons(i_payload_size+(8)); 00143 //IPv4のTxヘッダを書き込む。 00144 header->destipaddr=*i_dest_ip; 00145 header->srcipaddr =i_inst->uip_udp_conn.lipaddr; 00146 00147 NyLPC_TIPv4Header_writeTxIpHeader(header,UIP_PROTO_UDP); 00148 00149 //UDPのTxヘッダを書き込む 00150 //sorce & destination port 00151 udp->srcport = i_inst->uip_udp_conn.lport; 00152 udp->destport = NyLPC_htons(i_dest_port); 00153 udp->udpchksum= 0; 00154 00155 udp->udpchksum=~(NyLPC_TIPv4Header_makeTcpChecksum(header)); 00156 header->ipchksum = ~(NyLPC_TIPv4Header_makeIpChecksum(header)); 00157 } 00158 00159 00160 00161 00162 /** 00163 * この関数は、rxパケットを処理して、ソケットの状態を更新します。 00164 * uipサービスタスクが実行する関数です。 00165 * この関数はNyLPC_cTcpSocket_periodicと排他実行すること。 00166 */ 00167 NyLPC_TBool NyLPC_cMiMicIpUdpSocket_parseRx( 00168 NyLPC_TcMiMicIpUdpSocket_t* i_inst, 00169 const NyLPC_TcIPv4Payload_t* i_ipp) 00170 { 00171 NyLPC_TUInt16 tmp16; 00172 struct NyLPC_TIPv4RxInfo dheader; 00173 const void* data_offset; 00174 //ブロードキャストの場合、フラグを確認 00175 if(NyLPC_TIPv4Addr_isEqual(&(i_ipp->header->destipaddr),&NyLPC_TIPv4Addr_BROADCAST)){ 00176 if(!NyLPC_TUInt8_isBitOn(i_inst->uip_udp_conn.flags,NyLPC_cMiMicIpUdpSocket_FLAG_BROADCAST)){ 00177 goto DROP; 00178 } 00179 } 00180 //パラメータの計算 00181 tmp16=NyLPC_TUdpHeader_getHeaderLength(i_ipp->payload.tcp); 00182 //UDPペイロードの長さは、IPパケットの長さ-(IPヘッダ+UDPヘッダ) 00183 dheader.size=NyLPC_TIPv4Header_getPacketLength(i_ipp->header)-NyLPC_TIPv4Header_getHeaderLength(i_ipp->header)-tmp16; 00184 dheader.peer_ip=i_ipp->header->srcipaddr; 00185 dheader.peer_port=NyLPC_ntohs(i_ipp->payload.udp->srcport); 00186 dheader.ip=i_ipp->header->destipaddr; 00187 dheader.port=NyLPC_ntohs(i_ipp->payload.udp->destport); 00188 if(i_inst->as_handler.rx!=NULL){ 00189 if(!i_inst->as_handler.rx((NyLPC_TiUdpSocket_t*)(i_inst),i_ipp->payload.rawbuf+tmp16,&dheader)){ 00190 return NyLPC_TBool_FALSE;//UDPはReturnパケットなし 00191 } 00192 } 00193 //TCPデータオフセット 00194 data_offset=i_ipp->payload.rawbuf+tmp16; 00195 00196 //インスタンスをロックする。 00197 lockResource(i_inst); 00198 //受信キューへ追加(データ構造はsize[2]+data[n]).sizeに16ビットの受信サイズ,後続にデータ 00199 00200 //受信データサイズを確認 00201 if(NyLPC_cFifoBuffer_getSpace(&(i_inst->rxbuf))<dheader.size+sizeof(struct NyLPC_TIPv4RxInfo)){ 00202 goto DROP; 00203 } 00204 //バッファに格納可能なら、格納。 00205 NyLPC_cFifoBuffer_push(&(i_inst->rxbuf),&dheader,sizeof(struct NyLPC_TIPv4RxInfo)); 00206 NyLPC_cFifoBuffer_push(&(i_inst->rxbuf),data_offset,dheader.size); 00207 unlockResource(i_inst); 00208 return NyLPC_TBool_FALSE;//UDPはReturnパケットなし 00209 DROP: 00210 unlockResource(i_inst); 00211 return NyLPC_TBool_FALSE; 00212 } 00213 00214 00215 00216 00217 static void finalize(NyLPC_TiUdpSocket_t* i_inst) 00218 { 00219 NyLPC_Assert(NyLPC_cMiMicIpNetIf_isInitService()); 00220 00221 NyLPC_cFifoBuffer_finalize(&(i_inst->rxbuf)); 00222 NyLPC_cMiMicIpNetIf_releaseUdpSocketMemory((NyLPC_TcMiMicIpUdpSocket_t*)i_inst); 00223 return; 00224 } 00225 00226 00227 static void joinMulticast(NyLPC_TiUdpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr) 00228 { 00229 NyLPC_TcMiMicIpUdpSocket_t* inst=(NyLPC_TcMiMicIpUdpSocket_t*)i_inst; 00230 inst->uip_udp_conn.mcastaddr=*i_addr; 00231 } 00232 static void setBroadcast(NyLPC_TiUdpSocket_t* i_inst) 00233 { 00234 NyLPC_TcMiMicIpUdpSocket_t* inst=(NyLPC_TcMiMicIpUdpSocket_t*)i_inst; 00235 NyLPC_TUInt8_setBit(inst->uip_udp_conn.flags,NyLPC_cMiMicIpUdpSocket_FLAG_BROADCAST); 00236 } 00237 00238 00239 00240 /** 00241 * see Header file 00242 */ 00243 static NyLPC_TInt32 precv(NyLPC_TiUdpSocket_t* i_inst,const void** o_buf_ptr,const struct NyLPC_TIPv4RxInfo** o_info,NyLPC_TUInt32 i_wait_msec) 00244 { 00245 NyLPC_TcMiMicIpUdpSocket_t* inst=(NyLPC_TcMiMicIpUdpSocket_t*)i_inst; 00246 NyLPC_TUInt16 rlen; 00247 //タイマを生成 00248 NyLPC_TcStopwatch_t sw; 00249 NyLPC_cStopwatch_initialize(&sw); 00250 const char* b; 00251 const struct NyLPC_TIPv4RxInfo* rh; 00252 00253 //ESTABLISHED以外の場合は、エラー。 00254 NyLPC_cStopwatch_setNow(&sw); 00255 while(NyLPC_cStopwatch_elapseInMsec(&sw)<i_wait_msec) 00256 { 00257 //MUTEX LOCK 00258 lockResource(inst); 00259 rlen=NyLPC_cFifoBuffer_getLength(&(inst->rxbuf)); 00260 //MUTEX UNLOCK 00261 if(rlen>0){ 00262 //受信キューにデータがあれば返す。 00263 b=(char*)NyLPC_cFifoBuffer_getPtr(&(inst->rxbuf)); 00264 rh=(const struct NyLPC_TIPv4RxInfo*)b; 00265 *o_buf_ptr=b+sizeof(struct NyLPC_TIPv4RxInfo); 00266 if(o_info!=NULL){ 00267 *o_info=rh; 00268 } 00269 unlockResource(inst); 00270 NyLPC_cStopwatch_finalize(&sw); 00271 return rh->size; 00272 } 00273 unlockResource(inst); 00274 //タスクスイッチ 00275 NyLPC_cThread_yield(); 00276 }; 00277 NyLPC_cStopwatch_finalize(&sw); 00278 return 0; 00279 } 00280 /** 00281 * See header file 00282 */ 00283 static void pseek(NyLPC_TiUdpSocket_t* i_inst) 00284 { 00285 NyLPC_TcMiMicIpUdpSocket_t* inst=(NyLPC_TcMiMicIpUdpSocket_t*)i_inst; 00286 NyLPC_TUInt16 s; 00287 const struct NyLPC_TIPv4RxInfo* rh; 00288 //シークサイズを決定 00289 lockResource(inst); 00290 s=NyLPC_cFifoBuffer_getLength(&(inst->rxbuf)); 00291 if(s>0){ 00292 rh=(const struct NyLPC_TIPv4RxInfo*)NyLPC_cFifoBuffer_getPtr(&(inst->rxbuf)); 00293 NyLPC_cFifoBuffer_pop(&(inst->rxbuf),rh->size+sizeof(struct NyLPC_TIPv4RxInfo)); 00294 } 00295 unlockResource(inst); 00296 } 00297 00298 /** 00299 * See header file. 00300 */ 00301 static void* allocSendBuf(NyLPC_TiUdpSocket_t* i_inst,NyLPC_TUInt16 i_hint,NyLPC_TUInt16* o_buf_size,NyLPC_TUInt32 i_wait_in_msec) 00302 { 00303 NyLPC_TUInt16 s; 00304 void* buf; 00305 NyLPC_TcStopwatch_t sw; 00306 00307 NyLPC_cStopwatch_initialize(&sw); 00308 NyLPC_cStopwatch_startExpire(&sw,i_wait_in_msec); 00309 00310 //送信バッファを取得 00311 //@bug バッファが取れるまで通信がブロックするの。ここはなんとかしないと。 00312 for(;;){ 00313 buf=NyLPC_cMiMicIpNetIf_allocTxBuf(i_hint+(SIZE_OF_IPv4_UDPIP_HEADER),&s); 00314 if(buf!=NULL){ 00315 break; 00316 } 00317 //タイムアウト確認 00318 if(NyLPC_cStopwatch_isExpired(&sw)){ 00319 return NULL; 00320 } 00321 } 00322 //バッファサイズ確定。 00323 *o_buf_size=s; 00324 NyLPC_cStopwatch_finalize(&sw); 00325 return (NyLPC_TUInt8*)buf+SIZE_OF_IPv4_UDPIP_HEADER; 00326 } 00327 /** 00328 * See Header file. 00329 */ 00330 static void releaseSendBuf(NyLPC_TiUdpSocket_t* i_inst,void* i_buf_ptr) 00331 { 00332 NyLPC_cMiMicIpNetIf_releaseTxBuf((NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_UDPIP_HEADER); 00333 } 00334 00335 /** 00336 * See header file 00337 */ 00338 static NyLPC_TBool psend(NyLPC_TiUdpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_port,void* i_buf_ptr,int i_len) 00339 { 00340 void* buf; 00341 NyLPC_TcMiMicIpUdpSocket_t* inst=(NyLPC_TcMiMicIpUdpSocket_t*)i_inst; 00342 //ブロードキャストの場合、フラグを確認 00343 if(NyLPC_TIPv4Addr_isEqual(i_addr,&NyLPC_TIPv4Addr_BROADCAST)){ 00344 if(!NyLPC_TUInt8_isBitOn(inst->uip_udp_conn.flags,NyLPC_cMiMicIpUdpSocket_FLAG_BROADCAST)){ 00345 return NyLPC_TBool_FALSE; 00346 } 00347 } 00348 00349 //先頭ポインタは、i_buf-sizeof(SIZE_OF_IPv4_TCPIP_HEADER)固定 00350 buf=(NyLPC_TUInt8*)i_buf_ptr-SIZE_OF_IPv4_UDPIP_HEADER; 00351 00352 lockResource(inst); 00353 //IPv4ペイロードの書き込み 00354 setUdpTxBufHeader(inst,buf,i_addr,i_port,0x05,i_len); 00355 unlockResource(inst); 00356 // !(BroadCast || Multicast)の場合は送信前にARPテーブルをチェックする。 00357 if(!(NyLPC_TIPv4Addr_isEqual(i_addr,&NyLPC_TIPv4Addr_BROADCAST) || NyLPC_TIPv4Addr_isEqualWithMask(i_addr,&NyLPC_TIPv4Addr_MULTICAST,&NyLPC_TIPv4Addr_MULTICAST_MASK))){ 00358 if(!NyLPC_cMiMicIpNetIf_hasArpInfo(i_addr)){ 00359 NyLPC_cMiMicIpNetIf_sendArpRequest(i_addr); 00360 NyLPC_cThread_sleep(30); 00361 } 00362 } 00363 NyLPC_cMiMicIpNetIf_sendIPv4Tx(buf); 00364 NyLPC_cMiMicIpNetIf_releaseTxBuf(buf); 00365 return NyLPC_TBool_TRUE; 00366 } 00367 00368 /** 00369 * See header file. 00370 */ 00371 static NyLPC_TInt32 send(NyLPC_TiUdpSocket_t* i_inst,const struct NyLPC_TIPv4Addr* i_addr,NyLPC_TUInt16 i_port,const void* i_buf_ptr,NyLPC_TInt32 i_len,NyLPC_TUInt32 i_wait_in_msec) 00372 { 00373 NyLPC_TUInt16 s; 00374 int i; 00375 void* buf; 00376 if(i_len<1 || i_len>1200){ 00377 return 0; 00378 } 00379 //バッファの取得確率を上げるために2倍のサイズを要求 00380 for(i=0;i<3;i++){ 00381 buf=allocSendBuf(i_inst,i_len*2,&s,i_wait_in_msec); 00382 if(buf==NULL || s<i_len){ 00383 continue; 00384 } 00385 break; 00386 } 00387 if(buf==NULL){ 00388 return -1; 00389 } 00390 //送信サイズの計算 00391 memcpy(buf,i_buf_ptr,i_len); 00392 if(!psend(i_inst,i_addr,i_port,buf,i_len)){ 00393 releaseSendBuf(i_inst,buf); 00394 return -1; 00395 } 00396 return i_len; 00397 } 00398 00399 static void setOnRxHandler(NyLPC_TiUdpSocket_t* i_inst,NyLPC_TiUdpSocket_onRxHandler i_handler) 00400 { 00401 NyLPC_TcMiMicIpUdpSocket_t* inst=(NyLPC_TcMiMicIpUdpSocket_t*)i_inst; 00402 inst->as_handler.rx=i_handler; 00403 } 00404 static void setOnPeriodicHandler(NyLPC_TiUdpSocket_t* i_inst,NyLPC_TiUdpSocket_onPeriodicHandler i_handler) 00405 { 00406 NyLPC_TcMiMicIpUdpSocket_t* inst=(NyLPC_TcMiMicIpUdpSocket_t*)i_inst; 00407 inst->as_handler.periodic=i_handler; 00408 } 00409 static const struct NyLPC_TIPv4Addr* getSockIP(const NyLPC_TiUdpSocket_t* i_inst) 00410 { 00411 NyLPC_TcMiMicIpUdpSocket_t* inst=(NyLPC_TcMiMicIpUdpSocket_t*)i_inst; 00412 return &inst->uip_udp_conn.lipaddr; 00413 } 00414 00415 00416 void NyLPC_cMiMicIpUdpSocket_startService(NyLPC_TcMiMicIpUdpSocket_t* i_inst,const NyLPC_TcIPv4Config_t* i_config) 00417 { 00418 i_inst->uip_udp_conn.lipaddr=i_config->ip_addr; 00419 //受信バッファのクリア 00420 NyLPC_cFifoBuffer_clear(&(i_inst->rxbuf)); 00421 return; 00422 } 00423 00424 00425 void NyLPC_cMiMicIpUdpSocket_stopService(NyLPC_TcMiMicIpUdpSocket_t* i_inst) 00426 { 00427 //停止処理? 00428 } 00429 00430
Generated on Tue Jul 12 2022 15:46:16 by 1.7.2