This is Webservice SDK for mbed. LPCXpresso1769/LPC1768/FRDM-K64F/LPC4088
Dependents: MbedFileServer_1768MiniDK2 RedWireBridge IssueDebug_gcc MiMicRemoteMCU-for-Mbed ... more
NyLPC_cModUPnPDevice.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_cModUPnPDevice.h" 00027 #include "../NyLPC_cHttpdConnection_protected.h" 00028 #include "NyLPC_net.h" 00029 #include "NyLPC_stdlib.h" 00030 #include "NyLPC_http.h" 00031 #include <string.h> 00032 #include <ctype.h> 00033 00034 00035 00036 #define SIZE_OF_STRBUF 16 00037 struct TUPnPDeviceHeader 00038 { 00039 struct NyLPC_THttpBasicHeader super; 00040 //解析用 00041 NyLPC_TUInt8 _content_id; 00042 NyLPC_TUInt8 _astate; 00043 NyLPC_TInt16 _prefix_len; 00044 NyLPC_TcStr_t _tstr; 00045 NyLPC_TChar _tstr_buf[SIZE_OF_STRBUF]; 00046 /** 文字列のパーサ*/ 00047 union{ 00048 NyLPC_TInt16 service_idx; 00049 }content; 00050 }; 00051 00052 #define ST_PARSE_PATH 1 00053 #define ST_PARSE_QUERY_NAME 2 00054 00055 /** 00056 * コンテンツID定義(コンテンツ名に対応) 00057 */ 00058 #define CONTENT_ID_UNKNOWN 1 00059 #define CONTENT_ID_DEVICE_XML 2 00060 #define CONTENT_ID_CONTROL 3 00061 #define CONTENT_ID_EVENT 4 00062 00063 #define QNAME_ID_UNKNOWN 1 00064 #define QNAME_IDX 2 00065 00066 #define CONTENT_STR_DEVICE_XML "d.xml" 00067 #define CONTENT_STR_CONTROL_PATH "control" 00068 #define CONTENT_STR_EVENT_PATH "event" 00069 #define CONTENT_STR_XML_MIME_TYPE "text/xml" 00070 00071 00072 00073 00074 00075 static void writeDeviceNode(const struct NyLPC_TUPnPDevDescDevice* i_dev,NyLPC_TcHttpdConnection_t* i_connection,NyLPC_TUInt16* sidx) 00076 { 00077 //Required 00078 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00079 "<device>" 00080 "<deviceType>%s</deviceType>" 00081 "<friendlyName>%s</friendlyName>" 00082 "<manufacturer>%s</manufacturer>", 00083 i_dev->device_type, 00084 i_dev->frendly_name, 00085 i_dev->manufacturer); 00086 NyLPC_TInt16 i; 00087 //Optional 00088 if(i_dev->manufacturer_url!=NULL){ 00089 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00090 "<manufacturerURL>%s</manufacturerURL>", 00091 i_dev->manufacturer_url); 00092 } 00093 //Recommended 00094 if(i_dev->model_descriprion!=NULL){ 00095 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00096 "<modelDescription>%s</modelDescription>", 00097 i_dev->model_descriprion); 00098 }else{ 00099 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00100 "<modelDescription/>"); //Recommended 00101 } 00102 //Required 00103 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00104 "<modelName>%s</modelName>", 00105 i_dev->model_name); 00106 //Recommended 00107 if(i_dev->model_number!=NULL){ 00108 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00109 "<modelNumber>%s</modelNumber>", 00110 i_dev->model_number); 00111 }else{ 00112 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00113 "<modelNumber/>"); 00114 } 00115 //Optional 00116 if(i_dev->model_url!=NULL){ 00117 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00118 "<modelURL>%s</modelURL>", 00119 i_dev->model_url); 00120 } 00121 //Recommended 00122 if(i_dev->serial_number!=NULL){ 00123 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00124 "<serialNumber>%s</serialNumber>", 00125 i_dev->serial_number); 00126 }else{ 00127 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00128 "<serialNumber/>"); 00129 } 00130 //Required 00131 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00132 "<UDN>%s</UDN>", 00133 i_dev->udn); 00134 //Oprional 00135 if(i_dev->upc!=NULL){ 00136 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00137 "<UPC>%s</UPC>", 00138 i_dev->upc); 00139 } 00140 if(i_dev->number_of_icon>0){ 00141 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00142 "<iconList>"); 00143 for(i=0;i<i_dev->number_of_icon;i++){ 00144 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00145 "<icon>" 00146 "<mimetype>%s</mimetype>" 00147 "<width>%d</width>" 00148 "<height>%d</height>" 00149 "<depth>%d</depth>" 00150 "<url>%s</url>" 00151 "</icon>", 00152 i_dev->icons[i].mimetype, 00153 i_dev->icons[i].width, 00154 i_dev->icons[i].height, 00155 i_dev->icons[i].depth, 00156 i_dev->icons[i].url); 00157 } 00158 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00159 "</iconList>"); 00160 }else{ 00161 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00162 "<iconList/>"); 00163 } 00164 //Optional 00165 if(i_dev->number_of_service>0){ 00166 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00167 "<serviceList>"); 00168 for(i=0;i<i_dev->number_of_service;i++){ 00169 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00170 "<service>" 00171 "<serviceType>%s</serviceType>" 00172 "<serviceId>%s</serviceId>" 00173 "<SCPDURL>%s</SCPDURL>" 00174 "<controlURL>./control/%d</controlURL>" 00175 "<eventSubURL>./event/%d</eventSubURL>" 00176 "</service>", 00177 i_dev->services[i].scpd_url, 00178 i_dev->services[i].service_type, 00179 i_dev->services[i].service_id, 00180 (*sidx)+i, 00181 (*sidx)+i); 00182 } 00183 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00184 "</serviceList>"); 00185 } 00186 if(i_dev->number_of_devices>0){ 00187 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00188 "<deviceList>"); 00189 for(i=0;i<i_dev->number_of_devices;i++){ 00190 (*sidx)=(*sidx)+0x10; 00191 writeDeviceNode(i_dev->devices[i],i_connection,sidx); 00192 } 00193 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00194 "</deviceList>"); 00195 } 00196 if(i_dev->presentation_url!=NULL){ 00197 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00198 "<presentationURL>%s</presentationURL></device>", 00199 i_dev->presentation_url); 00200 } 00201 else{ 00202 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00203 "</device>"); 00204 } 00205 } 00206 NyLPC_TBool writeDeviceDescription(const struct NyLPC_TUPnPDevDescDevice* i_dev,NyLPC_TcHttpdConnection_t* i_connection) 00207 { 00208 NyLPC_cHttpdConnection_sendResponseBodyF(i_connection, 00209 "<?xml version=\"1.0\"?>" 00210 "<root xmlns=\"urn:schemas-upnp-org:device-1-0\">" 00211 "<specVersion><major>1</major><minor>0</minor></specVersion>"); 00212 writeDeviceNode(i_dev,i_connection,0); 00213 return NyLPC_cHttpdConnection_sendResponseBodyF(i_connection,"</root>"); 00214 } 00215 00216 00217 00218 00219 00220 /** 00221 * control,eventのServiceIndex部分をパースする。 00222 * [:str:]/[:HEX8:][:HEX8:] 00223 */ 00224 static NyLPC_TInt16 parseSidx(const NyLPC_TChar* i_str) 00225 { 00226 //先頭は/であること 00227 if(*i_str!='/'){ 00228 return -1; 00229 } 00230 //2桁の16進数であること 00231 if(!isxdigit((int)(*(i_str+1))) || !isxdigit((int)(*(i_str+2)))){ 00232 return -1; 00233 } 00234 //サービスID化 00235 return NyLPC_ctox(*(i_str+1))<<8 | NyLPC_ctox(*(i_str+2)); 00236 } 00237 00238 00239 static NyLPC_TBool urlHandler(NyLPC_TcHttpBasicHeaderParser_t* i_inst,NyLPC_TChar i_c,struct NyLPC_THttpBasicHeader* o_out) 00240 { 00241 00242 struct TUPnPDeviceHeader* out=(struct TUPnPDeviceHeader*)o_out; 00243 //読み飛ばし 00244 if(out->_prefix_len<0){ 00245 out->_prefix_len++; 00246 return NyLPC_TBool_TRUE;//読み飛ばし 00247 } 00248 if(out->_astate==ST_PARSE_PATH){ 00249 if(i_c!='\0' && i_c!='?'){ 00250 if(!NyLPC_cStr_put(&(out->_tstr),i_c)){ 00251 NyLPC_OnErrorGoto(ERROR); 00252 } 00253 return NyLPC_TBool_TRUE; 00254 } 00255 if(strcmp(NyLPC_cStr_str(&(out->_tstr)),CONTENT_STR_DEVICE_XML)==0){ 00256 out->_content_id=CONTENT_ID_DEVICE_XML; 00257 }else if(strncmp(CONTENT_STR_CONTROL_PATH,NyLPC_cStr_str(&(out->_tstr)),7)==0){ 00258 out->_content_id=CONTENT_ID_CONTROL; 00259 parseSidx(NyLPC_cStr_str(&(out->_tstr))+7); 00260 }else if(strncmp(CONTENT_STR_EVENT_PATH,NyLPC_cStr_str(&(out->_tstr)),5)==0){ 00261 out->_content_id=CONTENT_ID_EVENT; 00262 parseSidx(NyLPC_cStr_str(&(out->_tstr))+5); 00263 }else{ 00264 NyLPC_OnErrorGoto(ERROR); 00265 } 00266 NyLPC_cStr_clear(&(out->_tstr)); 00267 out->_astate=ST_PARSE_QUERY_NAME;//クエリ名解析へ 00268 return NyLPC_TBool_TRUE; 00269 } 00270 return NyLPC_TBool_TRUE; 00271 ERROR: 00272 return NyLPC_TBool_FALSE; 00273 } 00274 /** 00275 * デフォルトハンドラ 00276 */ 00277 static const struct NyLPC_TcHttpBasicHeaderParser_Handler handler= 00278 { 00279 NULL, 00280 urlHandler 00281 }; 00282 00283 00284 00285 00286 00287 00288 /** 00289 * コンストラクタ。 00290 */ 00291 void NyLPC_cModUPnPDevice_initialize(NyLPC_TcModUPnPDevice_t* i_inst,const NyLPC_TcUPnP_t* i_ref_upnp) 00292 { 00293 NyLPC_cModRomFiles_initialize(&i_inst->super,i_ref_upnp->_ref_root_path,NULL,0); 00294 i_inst->_ref_upnp=i_ref_upnp; 00295 } 00296 void NyLPC_cModUPnPDevice_finalize(NyLPC_TcModUPnPDevice_t* i_inst) 00297 { 00298 NyLPC_cModRomFiles_finalize(&i_inst->super); 00299 } 00300 /** 00301 * モジュールがコネクションをハンドリングできるかを返します。 00302 */ 00303 NyLPC_TBool NyLPC_cModUPnPDevice_canHandle(NyLPC_TcModUPnPDevice_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection) 00304 { 00305 return NyLPC_cModRomFiles_canHandle(&i_inst->super,i_connection); 00306 } 00307 00308 /** 00309 * モジュールを実行します。 00310 */ 00311 NyLPC_TBool NyLPC_cModUPnPDevice_execute(NyLPC_TcModUPnPDevice_t* i_inst,NyLPC_TcHttpdConnection_t* i_connection) 00312 { 00313 NyLPC_TUInt8 method_type; 00314 struct TUPnPDeviceHeader header; 00315 NyLPC_TcHttpBasicHeaderParser_t parser; 00316 00317 //リクエストParse済へ遷移(この関数の後はModが責任を持ってリクエストを返却) 00318 NyLPC_cHttpdConnection_setReqStatusParsed(i_connection); 00319 NyLPC_cStr_initialize(&header._tstr,header._tstr_buf,SIZE_OF_STRBUF); 00320 00321 //URL解析の準備 00322 header._prefix_len=-((NyLPC_TInt16)strlen(i_inst->super._ref_root_path)+2); 00323 header._astate=ST_PARSE_PATH; 00324 00325 NyLPC_cHttpBasicHeaderParser_initialize(&parser,&handler); 00326 NyLPC_cHttpBasicHeaderParser_parseInit(&parser,&(header.super)); 00327 //プリフェッチしたデータを流す 00328 NyLPC_cHttpdConnection_pushPrefetchInfo(i_connection,&parser,&header.super); 00329 //後続をストリームから取り込む 00330 if(!NyLPC_cHttpBasicHeaderParser_parseStream(&parser,NyLPC_cHttpdConnection_refStream(i_connection),&(header.super))){ 00331 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500); 00332 NyLPC_OnErrorGoto(Error2); 00333 } 00334 if(!NyLPC_cHttpBasicHeaderParser_parseFinish(&parser,&(header.super))){ 00335 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500); 00336 NyLPC_OnErrorGoto(Error2); 00337 } 00338 //GETかHEADに制限(Descriptionの場合だけ) 00339 method_type=NyLPC_cHttpdConnection_getMethod(i_connection); 00340 if(method_type!=NyLPC_THttpMethodType_GET && method_type!=NyLPC_THttpMethodType_HEAD) 00341 { 00342 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,405); 00343 NyLPC_OnErrorGoto(Error2); 00344 } 00345 //Request::ConnectionがClose設定,又はHTTP1.1では無い場合,CLOSE 00346 if(header.super.connection==NyLPC_THttpMessgeHeader_Connection_CLOSE || header.super.startline.req.version!=NyLPC_THttpVersion_11) 00347 { 00348 NyLPC_cHttpdConnection_setConnectionMode(i_connection,NyLPC_TcHttpdConnection_CONNECTION_MODE_CLOSE); 00349 } 00350 //CGIの実行 00351 switch(header._content_id) 00352 { 00353 case CONTENT_ID_DEVICE_XML: 00354 NyLPC_cHttpdConnection_sendResponseHeader(i_connection,200,CONTENT_STR_XML_MIME_TYPE,NULL); 00355 writeDeviceDescription(i_inst->_ref_upnp->ref_root_device,i_connection); 00356 //DeviceXML 00357 break; 00358 case CONTENT_ID_CONTROL: 00359 //SoapHandler 未実装 00360 case CONTENT_ID_EVENT: 00361 //EventHandler 未実装 00362 default: 00363 NyLPC_cHttpdUtils_sendErrorResponse(i_connection,500); 00364 NyLPC_OnErrorGoto(Error2); 00365 } 00366 NyLPC_cHttpBasicHeaderParser_finalize(&parser); 00367 NyLPC_cStr_finalize(&header._tstr); 00368 return NyLPC_TBool_TRUE; 00369 Error2: 00370 NyLPC_cHttpBasicHeaderParser_finalize(&parser); 00371 NyLPC_cStr_finalize(&header._tstr); 00372 return NyLPC_TBool_FALSE; 00373 } 00374
Generated on Tue Jul 12 2022 15:46:16 by 1.7.2