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_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 16:22:59 by
