ws/protocol.h
Go to the documentation of this file.
00001 /* 00002 * Copyright 2006-2009 Savarese Software Research Corporation 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * https://www.savarese.com/software/ApacheLicense-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00022 #ifndef __SSRC_WSPR_WS_PROTOCOL_H 00023 #define __SSRC_WSPR_WS_PROTOCOL_H 00024 00025 #include <ssrc/wispers/protocol.h> 00026 #include <ssrc/wispers/fcgi/parameter_map.h> 00027 #include <ssrc/wispers/session/protocol.h> 00028 #include <ssrc/wispers/utility/StringTo.h> 00029 #include <ssrc/wispers/utility/AppendToContainer.h> 00030 00031 #include <boost/preprocessor/stringize.hpp> 00032 00033 #ifdef WSPR_DEBUG 00034 #include <iostream> 00035 #endif 00036 00037 __BEGIN_NS_SSRC_WSPR_PROTOCOL 00038 00039 WSPR_DEFINE_PROTOCOL(WebService,ws); 00040 00041 __END_NS_SSRC_WSPR_PROTOCOL 00042 00043 __BEGIN_NS_SSRC_WSPR_WS 00044 00045 using std::string; 00046 using NS_SSRC_WISP_PROTOCOL::wisp_call_token; 00047 using NS_SSRC_WISP_PROTOCOL::MessageInfo; 00048 using NS_SSRC_WSPR_UTILITY::Properties; 00049 using NS_SSRC_WSPR_UTILITY::property_vector; 00050 using NS_SSRC_WSPR_UTILITY::properties_ptr; 00051 using NS_SSRC_WSPR_UTILITY::properties_unique_ptr; 00052 using NS_SSRC_WSPR_UTILITY::AppendToContainer; 00053 using NS_SSRC_WSPR_SESSION::session_ptr; 00054 00056 #define WSPR_WS_TYPE(service_base_str) "wspr.ws." service_base_str 00057 00058 inline Properties & set_web_event_header(Properties & properties, 00059 const string & protocol, 00060 const string & call) 00061 { 00062 properties.set(protocol, "protocol"); 00063 properties.set(call, "call"); 00064 return properties; 00065 } 00066 00067 inline Properties & set_web_event_header(Properties & properties, 00068 const string & protocol, 00069 const string & call, 00070 const gsid_type gsid) 00071 { 00072 properties.set(gsid, "gsid"); 00073 return set_web_event_header(properties, protocol, call); 00074 } 00075 00076 inline properties_unique_ptr 00077 web_event(const string & protocol, const string & call) { 00078 properties_unique_ptr props(new Properties); 00079 set_web_event_header(*props, protocol, call); 00080 return props; 00081 } 00082 00083 inline properties_unique_ptr 00084 web_event(const string & protocol, const string & call, const gsid_type gsid) { 00085 properties_unique_ptr props(new Properties); 00086 set_web_event_header(*props, protocol, call, gsid); 00087 return props; 00088 } 00089 00090 inline Properties & web_event_indirect(Properties & properties, 00091 const string & protocol, 00092 const string & call) 00093 { 00094 return set_web_event_header(properties, protocol, call); 00095 } 00096 00097 inline Properties & web_event_indirect(Properties & properties, 00098 const string & protocol, 00099 const string & call, 00100 const gsid_type gsid) 00101 { 00102 return set_web_event_header(properties, protocol, call, gsid); 00103 } 00104 00105 inline Properties & web_event_direct(Properties & properties, 00106 const string & protocol, 00107 const string & call) 00108 { 00109 Properties *node; 00110 property_vector & v = properties.create_property_vector("wspr", "event"); 00111 v.push_back(node = new Properties); 00112 return set_web_event_header(*node, protocol, call); 00113 } 00114 00115 inline Properties & web_event_direct(Properties & properties, 00116 const string & protocol, 00117 const string & call, 00118 const gsid_type gsid) 00119 { 00120 Properties *node; 00121 property_vector & v = properties.create_property_vector("wspr", "event"); 00122 v.push_back(node = new Properties); 00123 return set_web_event_header(*node, protocol, call, gsid); 00124 } 00125 00126 struct WebServiceCall { 00127 WISP_IMPORT(NS_SSRC_WSPR_FCGI, parameter_map); 00128 string call; 00129 parameter_map parameters; 00130 session_ptr session; 00131 00132 WebServiceCall() { } 00133 00134 WebServiceCall(const string & call, 00135 const parameter_map & parameters, 00136 const session_ptr & session = session_ptr()) : 00137 call(call), parameters(parameters), session(session) 00138 { } 00139 00140 bool is_parameter(const string & param_name) const { 00141 parameter_map::const_iterator && it = parameters.find(param_name); 00142 00143 if(it == parameters.end()) 00144 return false; 00145 00146 return true; 00147 } 00148 00149 template<typename param_type> 00150 bool get_parameter(const string & param_name, param_type & value) const 00151 SSRC_DECL_THROW(std::bad_cast) 00152 { 00153 parameter_map::const_iterator && it = parameters.find(param_name); 00154 00155 if(it == parameters.end()) 00156 return false; 00157 00158 value = utility::string_to<param_type>(it->second); 00159 00160 return true; 00161 } 00162 00163 template<typename param_type> 00164 param_type get_parameter(const string & param_name) const 00165 SSRC_DECL_THROW(std::bad_cast) 00166 { 00167 parameter_map::const_iterator && it = parameters.find(param_name); 00168 00169 if(it == parameters.end()) 00170 return param_type(); 00171 00172 return utility::string_to<param_type>(it->second); 00173 } 00174 00175 00176 template<typename container_type> 00177 unsigned int get_parameters(const string & param_name, 00178 container_type & container) const 00179 SSRC_DECL_THROW(std::bad_cast) 00180 { 00181 WISP_IMPORT_T(container_type, value_type); 00182 unsigned int count(0); 00183 std::pair<parameter_map::const_iterator,parameter_map::const_iterator> && 00184 range = parameters.equal_range(param_name); 00185 AppendToContainer<container_type> append(container); 00186 00187 while(range.first != range.second) { 00188 append(utility::string_to<value_type>(range.first->second)); 00189 ++range.first; 00190 ++count; 00191 } 00192 00193 return count; 00194 } 00195 00196 template<class Archive> 00197 void serialize(Archive & ar, const unsigned int) { 00198 ar & call & parameters & session; 00199 } 00200 }; 00201 00202 template<> inline 00203 bool WebServiceCall::get_parameter<string>(const string & param_name, 00204 string & value) const 00205 { 00206 parameter_map::const_iterator && it = parameters.find(param_name); 00207 00208 if(it == parameters.end()) 00209 return false; 00210 00211 value = it->second; 00212 00213 return true; 00214 } 00215 00216 template<> inline 00217 string WebServiceCall::get_parameter<string>(const string & param_name) const { 00218 parameter_map::const_iterator && it = parameters.find(param_name); 00219 00220 if(it == parameters.end()) 00221 return string(); 00222 00223 return it->second; 00224 } 00225 00226 #define __WS_DEFINE_CALL_PARAM(r, data, arg) \ 00227 BOOST_PP_TUPLE_ELEM(2, 0, arg) BOOST_PP_TUPLE_ELEM(2, 1, arg); 00228 00229 #define __WS_INIT_CALL_PARAM(r, data, i, arg) \ 00230 BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2, 1, arg)(call . get_parameter<BOOST_PP_TUPLE_ELEM(2, 0, arg)>(BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, arg)))) 00231 // This is for the benefit of client code that wants to define its own 00232 // macros that add extra functionality to the generated structure. 00233 #define __WS_CALL_PARAM(name, param_sequence) \ 00234 BOOST_PP_SEQ_FOR_EACH(__WS_DEFINE_CALL_PARAM, _, param_sequence) \ 00235 name (const NS_SSRC_WSPR_WS::WebServiceCall & call) SSRC_DECL_THROW(std::bad_cast) : \ 00236 BOOST_PP_SEQ_FOR_EACH_I(__WS_INIT_CALL_PARAM, call, param_sequence) \ 00237 { } \ 00238 00239 #define WS_CALL_PARAM(name, param_sequence) \ 00240 struct name { \ 00241 __WS_CALL_PARAM(name, param_sequence) \ 00242 } 00243 00244 template<typename ws_type, typename param_type> inline 00245 void ws_call(ws_type * impl, 00246 void (ws_type::* call_handler)(const WebServiceCall &, const param_type &, const MessageInfo &), 00247 const WebServiceCall & call, 00248 const MessageInfo & msginfo) 00249 { 00250 #ifdef WSPR_DEBUG 00251 try { 00252 #endif 00253 (impl->*call_handler)(call, param_type(call), msginfo); 00254 #ifdef WSPR_DEBUG 00255 } catch(const std::bad_cast & blc) { 00256 // TODO: log 00257 std::cerr << "bad parameters for " << call.call << std::endl 00258 << blc.what() << std::endl; 00259 for(WebServiceCall::parameter_map::const_iterator it = call.parameters.begin(); 00260 it != call.parameters.end(); ++it) 00261 { 00262 std::cerr << it->first << " : " << it->second << std::endl; 00263 } 00264 throw; 00265 } 00266 #endif 00267 } 00268 00269 struct WebServiceProtocol : 00270 public protocol::ServiceProtocol<protocol::WebService> 00271 { 00272 WISP_IMPORT(NS_SSRC_WSPR_FCGI, parameter_map); 00273 00274 enum MessageType { 00275 OneWay, 00276 TwoWay, 00277 Response, 00278 DeliverEvent, 00279 DeliverEvents 00280 }; 00281 00282 template<MessageType type> 00283 struct MessageCallBase : public protocol::MessageWebService<type> { 00284 WebServiceCall call; 00285 00286 MessageCallBase() { } 00287 00288 MessageCallBase(const string & call, 00289 const parameter_map & parameters, 00290 const session_ptr & session = session_ptr()) : 00291 call(call, parameters, session) 00292 { } 00293 00294 template<class Archive> 00295 void serialize(Archive & ar, const unsigned int) { 00296 ar & call; 00297 } 00298 }; 00299 00300 typedef MessageCallBase<OneWay> MessageOneWay; 00301 typedef MessageCallBase<TwoWay> MessageTwoWay; 00302 00303 // IMPORTANT: Changes to MessageResponse must be reflected in SWIG binding. 00304 // SWIG does not automatically handle nested classes, so we have a separate 00305 // SWIG interface that must be synchronized to this definition. 00306 class MessageResponse : public protocol::MessageWebService<Response> { 00307 enum Status { Succeeded, Failed, Error }; 00308 00309 unsigned int status; 00310 string status_msg; 00311 00312 void set_status(Status s, const string & msg) { 00313 status = s; 00314 status_msg = msg; 00315 } 00316 00317 public: 00318 session_ptr session; 00319 properties_ptr template_data; 00320 00321 explicit MessageResponse(const session_ptr & session = session_ptr()) : 00322 status(Succeeded), status_msg(), session(session), 00323 template_data(new Properties) 00324 { } 00325 00326 // template_data must be the result of new Properties or 0. 00327 explicit MessageResponse(const session_ptr & session, 00328 Properties * template_data) : 00329 status(Succeeded), status_msg(), session(session), 00330 template_data(template_data) 00331 { } 00332 00333 explicit MessageResponse(const session_ptr & session, 00334 const properties_ptr & template_data) : 00335 status(Succeeded), status_msg(), session(session), 00336 template_data(template_data) 00337 { } 00338 00339 void set_succeeded(const string & msg = ""){ 00340 set_status(Succeeded, msg); 00341 } 00342 00343 void set_failed(const string & msg = "") { 00344 set_status(Failed, msg); 00345 } 00346 00347 void set_error(const string & msg = "") { 00348 set_status(Error, msg); 00349 } 00350 00351 bool succeeded() const { return (status == Succeeded); } 00352 00353 bool failed() const { return (status == Failed); } 00354 00355 bool error() const { return (status == Error); } 00356 00357 const string & status_message() const { return status_msg; } 00358 00359 template<class Archive> 00360 void serialize(Archive & ar, const unsigned int) { 00361 ar & status & status_msg & session & template_data; 00362 } 00363 }; 00364 00365 00366 // This is for the EventQueue. It should go in a separate protocol. 00367 static string event_queue_ws_type() { 00368 return WSPR_WS_TYPE("event"); 00369 } 00370 00371 static string event_queue_ws_group() { 00372 return WSPR_WS_TYPE("event"); 00373 } 00374 00375 // This is for the EventQueue. It should go in a separate protocol. 00376 struct MessageDeliverEvent : 00377 public protocol::MessageWebService<DeliverEvent> 00378 { 00379 typedef std::vector<uid_type> key_container; 00380 key_container keys; 00381 properties_ptr template_data; 00382 00383 explicit MessageDeliverEvent(Properties * template_data = new Properties) : 00384 keys(), template_data(template_data) 00385 { } 00386 00387 explicit MessageDeliverEvent(const properties_ptr & template_data) : 00388 keys(), template_data(template_data) 00389 { } 00390 00391 template<class Archive> 00392 void serialize(Archive & ar, const unsigned int) { 00393 ar & keys & template_data; 00394 } 00395 }; 00396 00397 struct MessageDeliverEvents : 00398 public protocol::MessageWebService<DeliverEvents> 00399 { 00400 typedef std::vector<uid_type> key_container; 00401 typedef std::vector<Properties> event_container; 00402 key_container keys; 00403 event_container events; 00404 00405 explicit MessageDeliverEvents(const unsigned int size = 1) : 00406 keys(), events(size) 00407 { } 00408 00409 explicit MessageDeliverEvents(event_container && events) : 00410 keys(), events(events) 00411 { } 00412 00413 template<class Archive> 00414 void serialize(Archive & ar, const unsigned int) { 00415 ar & keys & events; 00416 } 00417 }; 00418 00419 WISP_ONE_WAY_CALL(caller_type, OneWay); 00420 WISP_ONE_WAY_CALL(caller_type, Response); 00421 WISP_ONE_WAY_CALL(caller_type, DeliverEvent); 00422 WISP_ONE_WAY_CALL(caller_type, DeliverEvents); 00423 00424 WISP_TWO_WAY_CALL(caller_type, TwoWay, Response); 00425 }; 00426 00427 struct WebServiceCallContextOneWay { 00428 session_ptr session; 00429 00430 WebServiceCallContextOneWay(const session_ptr & session) : 00431 session(session) 00432 { } 00433 }; 00434 00435 struct WebServiceCallContextTwoWay : public WebServiceCallContextOneWay { 00436 wisp_call_token token; 00437 string sender; 00438 00439 WebServiceCallContextTwoWay(const session_ptr & session, 00440 const wisp_call_token token, 00441 const string & sender) : 00442 WebServiceCallContextOneWay(session), token(token), sender(sender) 00443 { } 00444 }; 00445 00446 __END_NS_SSRC_WSPR_WS 00447 00448 #endif
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.