This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
NyLPC_cSsdpSocket.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 #include "NyLPC_cSsdpSocket.h" 00027 #include "NyLPC_http.h" 00028 #include "NyLPC_netif.h" 00029 00030 00031 #include <stdio.h> 00032 #include <string.h> 00033 00034 00035 00036 00037 00038 #define HTTP_SP 0x20 00039 00040 #define PARSE_NULL 0 00041 #define PARSE_ST 0x01 00042 #define PARSE_MAN 0x11 00043 #define PARSE_UNKNOWN 0xff 00044 00045 static const struct NyLPC_TIPv4Addr SSDP_MCAST_IPADDR=NyLPC_TIPv4Addr_pack(239,255,255,250); 00046 static const char* STR_UPNP_ROOT_DEVICE="upnp:rootdevice"; 00047 00048 struct TMSearchHeader 00049 { 00050 struct NyLPC_THttpBasicHeader super; 00051 00052 const struct NyLPC_TUPnPDeviceRecord* _ref_devices; 00053 /** 00054 * パーサのステータス 00055 */ 00056 NyLPC_TUInt8 st; 00057 /** 00058 * メモリ位置 00059 */ 00060 const NyLPC_TChar* _rpos; 00061 struct{ 00062 const NyLPC_TChar* st_str; 00063 const NyLPC_TChar* man_str; 00064 NyLPC_TUInt16 st_len; 00065 NyLPC_TUInt16 man_len; 00066 }result; 00067 }; 00068 00069 //とりあえずprivate 00070 void NyLPC_cSsdpSocket_notify(NyLPC_TcSsdpSocket_t* i_inst); 00071 00072 00073 static NyLPC_TBool urlHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out) 00074 { 00075 // *であるかを確認 未実装 00076 return NyLPC_TBool_TRUE; 00077 } 00078 00079 #define TIMEOUT_IN_MS 100 00080 00081 /** 00082 * SERVER MessageHeaderの値 00083 * 40文字以内であること。 00084 */ 00085 #define SERVER_MESSAGE_HEADER "MiMic/1.4 UPnP/1.0 MiMicUPnP/0.2" 00086 00087 00088 /** 00089 * MsearchResponseを格納したTxパケットをAllocする。 00090 * @param i_st 00091 * ST値 00092 * @param i_udn 00093 * DDESCのUDNの値 00094 * @param i_usn 00095 * USNのサフィックスパラメータ 00096 * @return 00097 * MsearchResponseを格納したTXメモリ 00098 */ 00099 static void* allocMsearchResponeTx( 00100 NyLPC_TcSsdpSocket_t* i_inst, 00101 const NyLPC_TChar* i_st, 00102 const NyLPC_TChar* i_udn, 00103 const NyLPC_TChar* i_usn, 00104 NyLPC_TUInt16 i_st_len, 00105 NyLPC_TInt16* o_len) 00106 { 00107 NyLPC_TChar* obuf; 00108 NyLPC_TUInt16 l; 00109 NyLPC_TUInt16 len_usn=(NyLPC_TUInt16)((i_usn!=NULL)?strlen(i_usn):0); 00110 NyLPC_TUInt16 len_udn=(NyLPC_TUInt16)strlen(i_udn); 00111 NyLPC_TUInt16 len_location=(NyLPC_TUInt16)strlen(i_inst->location_path); 00112 00113 // //161Byte 00114 // "HTTP/1.1 200 OK\r\n" //15+2=17 00115 // "CACHE-CONTROL: max-age = nnnn\r\n" //29+2=31 00116 // "SERVER: [:40byte:]\r\n" //8+40+2=50 00117 // "EXT: \r\n" //5+2 = 7 00118 // "LOCATION: http://xxx.xxx.xxx.xxx:nnnnn/%s/d.xml\r\n" //34+2=46 00119 // "USN: %s%s\r\n" //5+2=7 00120 // "ST: %s\r\n\r\n" //4+4=8 00121 l=166+len_location+len_usn+len_udn+i_st_len; 00122 obuf=NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket,l,&l,TIMEOUT_IN_MS); 00123 00124 if(obuf==NULL){ 00125 return NULL; 00126 } 00127 //必要なメモリサイズを確保できた? 00128 if(l<161+len_location+len_usn+len_udn+i_st_len) 00129 { 00130 NyLPC_iUdpSocket_releaseSendBuf(i_inst->_socket,obuf); 00131 return NULL; 00132 } 00133 //ワーク変数lの再初期化 00134 l=0; 00135 strcpy(obuf, 00136 "HTTP/1.1 200 OK\r\n" 00137 "CACHE-CONTROL: max-age = 300\r\n" 00138 "SERVER: "SERVER_MESSAGE_HEADER"\r\n" 00139 "EXT: \r\n" 00140 "LOCATION: http://"); 00141 l+=strlen(obuf); 00142 //IP addr:port\r\n 00143 l+=NyLPC_TIPv4Addr_toString(NyLPC_iUdpSocket_getSockIP(i_inst->_socket),obuf+l); 00144 *(obuf+l)=':'; 00145 l+=1+NyLPC_itoa(i_inst->location_port,obuf+l+1,10); 00146 *(obuf+l)='/';l++; 00147 memcpy(obuf+l,i_inst->location_path,len_location);l+=len_location; 00148 memcpy(obuf+l,"/d.xml",6);l+=6; 00149 *(obuf+l+0)='\r'; 00150 *(obuf+l+1)='\n'; 00151 l+=2; 00152 //USN: uuid:xxx 00153 memcpy(obuf+l,"USN: ",5); l+=5; 00154 memcpy(obuf+l,i_udn,len_udn); l+=len_udn; //uuid:xxx 00155 if(i_usn!=NULL){ 00156 *(obuf+l+0)=':'; 00157 *(obuf+l+1)=':'; 00158 l+=2; 00159 memcpy(obuf+l,i_usn,len_usn);l+=len_usn; //usn:xxx 00160 } 00161 *(obuf+l+0)='\r'; 00162 *(obuf+l+1)='\n'; 00163 l+=2; 00164 //ST 00165 memcpy(obuf+l,"ST: ",4); l+=4; 00166 memcpy(obuf+l,i_st,i_st_len);l+=i_st_len; 00167 memcpy(obuf+l,"\r\n\r\n",4); l+=4; 00168 *o_len=l; 00169 return obuf; 00170 } 00171 00172 00173 /** 00174 * MsearchResponseを格納したTxパケットをAllocする。 00175 * @param i_udn 00176 * udn 00177 * @param i_udn 00178 * DDESCのUDNの値 00179 * @param i_usn 00180 * USNのサフィックスパラメータ 00181 * @return 00182 * MsearchResponseを格納したTXメモリ 00183 */ 00184 static void* allocNotifyTx( 00185 NyLPC_TcSsdpSocket_t* i_inst, 00186 const NyLPC_TChar* i_udn, 00187 const NyLPC_TChar* i_usn, 00188 NyLPC_TInt16* o_len) 00189 { 00190 NyLPC_TChar* obuf; 00191 NyLPC_TUInt16 l,l2; 00192 NyLPC_TUInt16 len_usn=(NyLPC_TUInt16)((i_usn!=NULL)?strlen(i_usn):0); 00193 NyLPC_TUInt16 len_udn=(NyLPC_TUInt16)strlen(i_udn); 00194 NyLPC_TUInt16 len_location=(NyLPC_TUInt16)strlen(i_inst->location_path); 00195 00196 // //193Byte 00197 // "NOTIFY * HTTP/1.1\r\n" //15+2=17 00198 // "HOST: 239.255.255.250:1900\r\n" //26+2=28 00199 // "CACHE-CONTROL: max-age = 1800\r\n" //29+2=31 00200 // "SERVER: [:40byte:]\r\n" //8+40+2=50 00201 // "NTS: ssdp:alive\r\n" //14+2 =17 00202 // "LOCATION: http://xxx.xxx.xxx.xxx:nnnnn/%s/d.xml\r\n"//44+2=46 00203 // "USN: %s%s\r\n" //5+2=7 00204 // "NT: %s\r\n\r\n" //4+4=8 00205 l2=204+len_location+len_usn+len_udn+((len_usn>0)?len_usn:len_udn); 00206 obuf=NyLPC_iUdpSocket_allocSendBuf(i_inst->_socket,l2,&l,TIMEOUT_IN_MS); 00207 if(obuf==NULL){ 00208 return NULL; 00209 } 00210 //必要なメモリサイズを確保できた? 00211 if(l<l2) 00212 { 00213 NyLPC_iUdpSocket_releaseSendBuf(i_inst->_socket,obuf); 00214 return NULL; 00215 } 00216 //ワーク変数lの再初期化 00217 l=0; 00218 strcpy(obuf, 00219 "NOTIFY * HTTP/1.1\r\n" 00220 "HOST: 239.255.255.250:1900\r\n" 00221 "CACHE-CONTROL: max-age = 300\r\n" 00222 "SERVER: "SERVER_MESSAGE_HEADER"\r\n" 00223 "NTS: ssdp:alive\r\n" 00224 "LOCATION: http://"); 00225 l+=strlen(obuf); 00226 //IP addr:port\r\n 00227 l+=NyLPC_TIPv4Addr_toString(NyLPC_iUdpSocket_getSockIP(i_inst->_socket),obuf+l); 00228 *(obuf+l)=':'; 00229 l+=1+NyLPC_itoa(i_inst->location_port,obuf+l+1,10); 00230 *(obuf+l)='/';l++; 00231 memcpy(obuf+l,i_inst->location_path,len_location);l+=len_location; 00232 memcpy(obuf+l,"/d.xml",6);l+=6; 00233 *(obuf+l+0)='\r'; 00234 *(obuf+l+1)='\n'; 00235 l+=2; 00236 //USN: uuid:xxx 00237 memcpy(obuf+l,"USN: ",5); l+=5; 00238 memcpy(obuf+l,i_udn,len_udn); l+=len_udn; //uuid:xxx 00239 if(i_usn!=NULL){ 00240 *(obuf+l+0)=':'; 00241 *(obuf+l+1)=':'; 00242 l+=2; 00243 memcpy(obuf+l,i_usn,len_usn);l+=len_usn; //usn:xxx 00244 } 00245 *(obuf+l+0)='\r'; 00246 *(obuf+l+1)='\n'; 00247 l+=2; 00248 //NT 00249 memcpy(obuf+l,"NT: ",4); l+=4; 00250 if(len_usn>0){ 00251 memcpy(obuf+l,i_usn,len_usn);l+=len_usn; 00252 }else{ 00253 memcpy(obuf+l,i_udn,len_udn);l+=len_udn; 00254 } 00255 memcpy(obuf+l,"\r\n\r\n",4); l+=4; 00256 *o_len=l; 00257 return obuf; 00258 } 00259 00260 00261 static NyLPC_TBool messageHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,const NyLPC_TChar* i_name,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out) 00262 { 00263 struct TMSearchHeader* header=(struct TMSearchHeader*)o_out; 00264 switch(header->st) 00265 { 00266 case PARSE_NULL: 00267 if(NyLPC_stricmp(i_name,"ST")==0){ 00268 //mode==ST 00269 header->st=PARSE_ST; 00270 header->result.st_str=NULL; 00271 }else if(NyLPC_stricmp(i_name,"MAN")==0){ 00272 //mode=MAN 00273 header->st=PARSE_MAN; 00274 header->result.man_str=NULL; 00275 }else{ 00276 header->st=PARSE_UNKNOWN; 00277 //無視 00278 } 00279 break; 00280 case PARSE_ST: 00281 if((header->result.st_str==NULL) && (i_c!=HTTP_SP)){ 00282 header->result.st_str=header->_rpos; 00283 } 00284 if(i_c=='\0') 00285 { 00286 header->result.st_len=header->_rpos-header->result.st_str-1; 00287 header->st=PARSE_NULL; 00288 } 00289 break; 00290 case PARSE_MAN: 00291 if((header->result.man_str==NULL) && (i_c!=HTTP_SP)){ 00292 header->result.man_str=header->_rpos; 00293 } 00294 if(i_c=='\0'){ 00295 header->result.man_len=header->_rpos-header->result.man_str-1; 00296 header->st=PARSE_NULL; 00297 } 00298 break; 00299 case PARSE_UNKNOWN: 00300 default: 00301 if(i_c=='\0'){ 00302 header->st=PARSE_NULL; 00303 } 00304 break; 00305 } 00306 return NyLPC_TBool_TRUE; 00307 } 00308 00309 /** 00310 * デフォルトハンドラ 00311 */ 00312 static const struct NyLPC_TcHttpBasicHeaderParser_Handler handler= 00313 { 00314 messageHandler, 00315 urlHandler 00316 }; 00317 00318 static NyLPC_TBool parseHeader(struct TMSearchHeader* i_out,const void* i_rx,NyLPC_TInt16 i_rx_size) 00319 { 00320 NyLPC_TInt16 i; 00321 NyLPC_TcHttpBasicHeaderParser_t parser; 00322 //headerの初期化 00323 i_out->st=PARSE_NULL; 00324 i_out->result.st_str=NULL; 00325 i_out->result.man_str=NULL; 00326 NyLPC_cHttpBasicHeaderParser_initialize(&parser,&handler); 00327 NyLPC_cHttpBasicHeaderParser_parseInit(&parser,&(i_out->super)); 00328 for(i=0;i<i_rx_size;i++){ 00329 i_out->_rpos=((const char*)(i_rx))+i; 00330 if(NyLPC_cHttpBasicHeaderParser_parseChar(&parser,i_out->_rpos,1,&(i_out->super))<0){ 00331 NyLPC_cHttpBasicHeaderParser_finalize(&parser); 00332 return NyLPC_TBool_FALSE;//ERROR 00333 } 00334 } 00335 NyLPC_cHttpBasicHeaderParser_parseFinish(&parser,&(i_out->super)); 00336 NyLPC_cHttpBasicHeaderParser_finalize(&parser); 00337 return NyLPC_TBool_TRUE;//OK 00338 } 00339 00340 static NyLPC_TBool onPacket(NyLPC_TiUdpSocket_t* i_sock,const void* i_buf,const struct NyLPC_TIPv4RxInfo* i_info) 00341 { 00342 //パケット解析 00343 void* tx; 00344 struct TMSearchHeader header; 00345 NyLPC_TInt16 tx_len; 00346 NyLPC_TInt8 i,i2; 00347 NyLPC_TcSsdpSocket_t* inst=((NyLPC_TcSsdpSocket_t*)i_sock->_tag); 00348 if(!parseHeader(&header,i_buf,i_info->size)){ 00349 NyLPC_OnErrorGoto(ERROR1); 00350 } 00351 //resultチェック 00352 if(header.result.man_str==NULL || header.result.st_str==NULL){ 00353 NyLPC_OnErrorGoto(ERROR1); 00354 } 00355 //Methodチェック 00356 if(header.super.startline.req.method!=NyLPC_THttpMethodType_M_SEARCH){ 00357 NyLPC_OnErrorGoto(ERROR1); 00358 } 00359 00360 //MANチェック 00361 if(strncmp("\"ssdp:discover\"",header.result.man_str,15)!=0){ 00362 NyLPC_OnErrorGoto(ERROR1); 00363 } 00364 //STによる処理分岐 00365 if(strncmp("ssdp:all",header.result.st_str,8)==0){ 00366 tx=allocMsearchResponeTx( 00367 inst,header.result.st_str, 00368 inst->ref_device_record[0]->udn,STR_UPNP_ROOT_DEVICE, 00369 header.result.st_len, 00370 &tx_len); 00371 if(tx==NULL){ 00372 NyLPC_OnErrorGoto(ERROR1); 00373 } 00374 if(!NyLPC_iUdpSocket_psend(i_sock,&i_info->peer_ip,i_info->peer_port,tx,tx_len)){ 00375 NyLPC_OnErrorGoto(ERROR2); 00376 } 00377 //全デバイスの送信 00378 for(i=0;i<inst->number_of_device;i++){ 00379 tx=allocMsearchResponeTx( 00380 inst,header.result.st_str, 00381 inst->ref_device_record[i]->udn,inst->ref_device_record[i]->device_type, 00382 header.result.st_len, 00383 &tx_len); 00384 if(tx==NULL){ 00385 NyLPC_OnErrorGoto(ERROR1); 00386 } 00387 if(!NyLPC_iUdpSocket_psend(i_sock,&i_info->peer_ip,i_info->peer_port,tx,tx_len)){ 00388 NyLPC_OnErrorGoto(ERROR2); 00389 } 00390 for(i2=0;i2<inst->ref_device_record[i]->number_of_service;i2++){ 00391 //serviceに一致 00392 tx=allocMsearchResponeTx( 00393 inst,header.result.st_str, 00394 inst->ref_device_record[i]->udn,inst->ref_device_record[i]->services[i2].service_type, 00395 header.result.st_len, 00396 &tx_len); 00397 if(tx==NULL){ 00398 NyLPC_OnErrorGoto(ERROR1); 00399 } 00400 if(!NyLPC_iUdpSocket_psend(i_sock,&i_info->peer_ip,i_info->peer_port,tx,tx_len)){ 00401 NyLPC_OnErrorGoto(ERROR2); 00402 } 00403 } 00404 } 00405 }else if(strncmp("uuid:",header.result.st_str,5)==0){ 00406 //UDNの一致するデバイスの送信 00407 NyLPC_TInt16 i; 00408 for(i=inst->number_of_device-1;i>=0;i--){ 00409 if(strncmp(header.result.st_str,inst->ref_device_record[i]->udn,header.result.st_len)==0){ 00410 //UDN一致 00411 tx=allocMsearchResponeTx( 00412 inst,header.result.st_str, 00413 inst->ref_device_record[i]->udn,NULL, 00414 header.result.st_len, 00415 &tx_len); 00416 if(tx==NULL){ 00417 NyLPC_OnErrorGoto(ERROR1); 00418 } 00419 if(!NyLPC_iUdpSocket_psend(i_sock,&i_info->peer_ip,i_info->peer_port,tx,tx_len)){ 00420 NyLPC_OnErrorGoto(ERROR2); 00421 } 00422 break;//送信処理終了 00423 } 00424 } 00425 }else if(strncmp(STR_UPNP_ROOT_DEVICE,header.result.st_str,15)==0){ 00426 //rootDeviceはSTR_UPNP_ROOT_DEVICE 00427 tx=allocMsearchResponeTx( 00428 inst,header.result.st_str, 00429 inst->ref_device_record[0]->udn,STR_UPNP_ROOT_DEVICE, 00430 header.result.st_len, 00431 &tx_len); 00432 if(tx==NULL){ 00433 NyLPC_OnErrorGoto(ERROR1); 00434 } 00435 if(!NyLPC_iUdpSocket_psend(i_sock,&i_info->peer_ip,i_info->peer_port,tx,tx_len)){ 00436 NyLPC_OnErrorGoto(ERROR2); 00437 } 00438 }else if(strncmp("urn:",header.result.st_str,4)==0){ 00439 for(i=0;i<inst->number_of_device;i++){ 00440 //urn一致チェック 00441 if(strncmp(inst->ref_device_record[i]->device_type,header.result.st_str,header.result.st_len)==0){ 00442 //deviceに一致 00443 tx=allocMsearchResponeTx( 00444 inst,header.result.st_str, 00445 inst->ref_device_record[i]->udn,inst->ref_device_record[i]->device_type, 00446 header.result.st_len, 00447 &tx_len); 00448 if(tx==NULL){ 00449 NyLPC_OnErrorGoto(ERROR1); 00450 } 00451 if(!NyLPC_iUdpSocket_psend(i_sock,&i_info->peer_ip,i_info->peer_port,tx,tx_len)){ 00452 NyLPC_OnErrorGoto(ERROR2); 00453 } 00454 continue; 00455 } 00456 for(i2=0;i2<inst->ref_device_record[i]->number_of_service;i2++){ 00457 if(strncmp(inst->ref_device_record[i]->services[i2].service_type,header.result.st_str,header.result.st_len)==0){ 00458 //serviceに一致 00459 tx=allocMsearchResponeTx( 00460 inst,header.result.st_str, 00461 inst->ref_device_record[i]->udn,inst->ref_device_record[i]->services[i2].service_type, 00462 header.result.st_len, 00463 &tx_len); 00464 if(tx==NULL){ 00465 NyLPC_OnErrorGoto(ERROR1); 00466 } 00467 if(!NyLPC_iUdpSocket_psend(i_sock,&i_info->peer_ip,i_info->peer_port,tx,tx_len)){ 00468 NyLPC_OnErrorGoto(ERROR2); 00469 } 00470 } 00471 } 00472 } 00473 } 00474 //正常終了 00475 return NyLPC_TBool_FALSE; 00476 ERROR2: 00477 NyLPC_iUdpSocket_releaseSendBuf(i_sock,tx); 00478 ERROR1: 00479 return NyLPC_TBool_FALSE; 00480 } 00481 00482 #define SSDP_NOTIFY_INTERVAL 150*1000 //300*0.5*1000 00483 #define FLAG_ORDER_START_SERVICE 0 00484 #define FLAG_ORDER_STOP_SERVICE 1 00485 #define FLAG_IS_SERVICE_RUNNING 2 00486 00487 static void onPeriodic(NyLPC_TiUdpSocket_t* i_sock) 00488 { 00489 NyLPC_TcSsdpSocket_t* inst=(NyLPC_TcSsdpSocket_t*)i_sock->_tag; 00490 if(NyLPC_TUInt8_isBitOn(inst->_flags,FLAG_IS_SERVICE_RUNNING)){ 00491 //実行中 00492 //停止要求着てる? 00493 if(NyLPC_TUInt8_isBitOn(inst->_flags,FLAG_ORDER_STOP_SERVICE)) 00494 { 00495 //状態変更 00496 NyLPC_TUInt8_unsetBit(inst->_flags,FLAG_IS_SERVICE_RUNNING); 00497 //要求フラグクリア 00498 NyLPC_TUInt8_unsetBit(inst->_flags,FLAG_ORDER_STOP_SERVICE); 00499 //@bug ByeBye送信しろ 00500 }else if(NyLPC_cStopwatch_isExpired(&inst->_periodic_sw)){ 00501 //Notify送信 00502 NyLPC_cSsdpSocket_notify(inst); 00503 //タイマ再始動 00504 NyLPC_cStopwatch_startExpire(&inst->_periodic_sw,SSDP_NOTIFY_INTERVAL); 00505 } 00506 }else{ 00507 //停止中 00508 //開始要求着てる? 00509 if(NyLPC_TUInt8_isBitOn(inst->_flags,FLAG_ORDER_START_SERVICE)) 00510 { 00511 //状態変更 00512 NyLPC_TUInt8_setBit(inst->_flags,FLAG_IS_SERVICE_RUNNING); 00513 //要求フラグクリア 00514 NyLPC_TUInt8_unsetBit(inst->_flags,FLAG_ORDER_START_SERVICE); 00515 //次回expireするように 00516 NyLPC_cStopwatch_startExpire(&inst->_periodic_sw,SSDP_NOTIFY_INTERVAL); 00517 } 00518 } 00519 } 00520 00521 /** 00522 * デバイスツリーを展開する。 00523 */ 00524 static void expandDeviceTree(NyLPC_TcSsdpSocket_t* i_inst,const struct NyLPC_TUPnPDevDescDevice* i_dev) 00525 { 00526 NyLPC_TUInt16 i; 00527 if(i_inst->number_of_device>=NyLPC_TcSsdpSocket_MAX_DEVICES){ 00528 NyLPC_Warning();// 00529 } 00530 i_inst->ref_device_record[i_inst->number_of_device]=i_dev; 00531 i_inst->number_of_device++; 00532 for(i=0;i<i_dev->number_of_devices;i++){ 00533 expandDeviceTree(i_inst,i_dev->devices[i]); 00534 } 00535 return; 00536 } 00537 00538 void NyLPC_cSsdpSocket_initialize( 00539 NyLPC_TcSsdpSocket_t* i_inst, 00540 const struct NyLPC_TUPnPDevDescDevice* i_ref_dev_record, 00541 NyLPC_TUInt16 i_server_port,const NyLPC_TChar* i_ref_location_path) 00542 { 00543 i_inst->_socket=NyLPC_cNet_createUdpSocketEx(1900,NyLPC_TSocketType_UDP_NOBUF); 00544 i_inst->_socket->_tag=i_inst; 00545 00546 NyLPC_iUdpSocket_setOnRxHandler(i_inst->_socket,onPacket); 00547 NyLPC_iUdpSocket_setOnPeriodicHandler(i_inst->_socket,onPeriodic); 00548 00549 NyLPC_iUdpSocket_joinMulticast(i_inst->_socket,&SSDP_MCAST_IPADDR); 00550 i_inst->_flags=0; 00551 NyLPC_cStopwatch_initialize(&(i_inst->_periodic_sw)); 00552 i_inst->number_of_device=0; 00553 expandDeviceTree(i_inst,i_ref_dev_record); 00554 i_inst->location_port=i_server_port; 00555 i_inst->location_path=i_ref_location_path; 00556 } 00557 void NyLPC_cSsdpSocket_finalize(NyLPC_TcSsdpSocket_t* i_inst) 00558 { 00559 NyLPC_cStopwatch_finalize(&(i_inst->_periodic_sw)); 00560 NyLPC_iUdpSocket_finalize(i_inst->_socket); 00561 } 00562 00563 void NyLPC_cSsdpSocket_start(NyLPC_TcSsdpSocket_t* i_inst) 00564 { 00565 //Notifyを3回送信 00566 NyLPC_TInt16 i; 00567 NyLPC_cSsdpSocket_notify(i_inst); 00568 for(i=0;i<2;i++){ 00569 NyLPC_cThread_sleep(800); 00570 NyLPC_cSsdpSocket_notify(i_inst); 00571 } 00572 00573 //ストップウォッチの開始要求 00574 NyLPC_TUInt8_setBit(i_inst->_flags,FLAG_ORDER_START_SERVICE); 00575 do{ 00576 NyLPC_cThread_sleep(10); 00577 //開始フラグがクリアされるまでループ 00578 }while(NyLPC_TUInt8_isBitOn(i_inst->_flags,FLAG_ORDER_START_SERVICE)); 00579 } 00580 void NyLPC_cSsdpSocket_stop(NyLPC_TcSsdpSocket_t* i_inst) 00581 { 00582 //今は使えない。 00583 NyLPC_Abort(); 00584 NyLPC_TUInt8_setBit(i_inst->_flags,FLAG_ORDER_STOP_SERVICE); 00585 do{ 00586 NyLPC_cThread_sleep(10); 00587 //開始フラグがクリアされるまでループ 00588 }while(NyLPC_TUInt8_isBitOn(i_inst->_flags,FLAG_ORDER_STOP_SERVICE)); 00589 } 00590 void NyLPC_cSsdpSocket_notify(NyLPC_TcSsdpSocket_t* i_inst) 00591 { 00592 void* tx; 00593 NyLPC_TInt16 tx_len; 00594 NyLPC_TUInt8 i,i2; 00595 //rootdevice 00596 tx=allocNotifyTx( 00597 i_inst, 00598 i_inst->ref_device_record[0]->udn,STR_UPNP_ROOT_DEVICE, 00599 &tx_len); 00600 if(tx==NULL){ 00601 NyLPC_OnErrorGoto(ERROR1); 00602 } 00603 if(!NyLPC_iUdpSocket_psend(i_inst->_socket,&SSDP_MCAST_IPADDR,1900,tx,tx_len)){ 00604 NyLPC_OnErrorGoto(ERROR2); 00605 } 00606 //all device 00607 for(i=0;i<i_inst->number_of_device;i++){ 00608 //uuid 00609 tx=allocNotifyTx( 00610 i_inst, 00611 i_inst->ref_device_record[i]->udn,NULL, 00612 &tx_len); 00613 if(tx==NULL){ 00614 NyLPC_OnErrorGoto(ERROR1); 00615 } 00616 if(!NyLPC_iUdpSocket_psend(i_inst->_socket,&SSDP_MCAST_IPADDR,1900,tx,tx_len)){ 00617 NyLPC_OnErrorGoto(ERROR2); 00618 } 00619 //devicatype 00620 tx=allocNotifyTx( 00621 i_inst, 00622 i_inst->ref_device_record[i]->udn,i_inst->ref_device_record[i]->device_type, 00623 &tx_len); 00624 if(tx==NULL){ 00625 NyLPC_OnErrorGoto(ERROR1); 00626 } 00627 if(!NyLPC_iUdpSocket_psend(i_inst->_socket,&SSDP_MCAST_IPADDR,1900,tx,tx_len)){ 00628 NyLPC_OnErrorGoto(ERROR2); 00629 } 00630 for(i2=0;i2<i_inst->ref_device_record[i]->number_of_service;i2++){ 00631 tx=allocNotifyTx( 00632 i_inst, 00633 i_inst->ref_device_record[i]->udn,i_inst->ref_device_record[i]->services[i2].service_type, 00634 &tx_len); 00635 if(tx==NULL){ 00636 NyLPC_OnErrorGoto(ERROR1); 00637 } 00638 if(!NyLPC_iUdpSocket_psend(i_inst->_socket,&SSDP_MCAST_IPADDR,1900,tx,tx_len)){ 00639 NyLPC_OnErrorGoto(ERROR2); 00640 } 00641 } 00642 } 00643 return; 00644 ERROR2: 00645 NyLPC_iUdpSocket_releaseSendBuf(i_inst->_socket,tx); 00646 ERROR1: 00647 return; 00648 } 00649
Generated on Tue Jul 12 2022 15:46:16 by 1.7.2