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.
Fork of libMiMic by
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 16:22:58 by
