Branch data Line data Source code
1 : : /*
2 : : * Copyright 2006-2009 Savarese Software Research Corporation
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at
7 : : *
8 : : * https://www.savarese.com/software/ApacheLicense-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : /**
18 : : * @file
19 : : * This header defines the WebService messaging protocol.
20 : : */
21 : :
22 : : #ifndef __SSRC_WSPR_WS_PROTOCOL_H
23 : : #define __SSRC_WSPR_WS_PROTOCOL_H
24 : :
25 : : #include <ssrc/wispers/protocol.h>
26 : : #include <ssrc/wispers/fcgi/parameter_map.h>
27 : : #include <ssrc/wispers/session/protocol.h>
28 : : #include <ssrc/wispers/utility/StringTo.h>
29 : : #include <ssrc/wispers/utility/AppendToContainer.h>
30 : :
31 : : #include <boost/preprocessor/stringize.hpp>
32 : :
33 : : #ifdef WSPR_DEBUG
34 : : #include <iostream>
35 : : #endif
36 : :
37 : : __BEGIN_NS_SSRC_WSPR_PROTOCOL
38 : :
39 [ + - ]: 5 : WSPR_DEFINE_PROTOCOL(WebService,ws);
40 : :
41 : : __END_NS_SSRC_WSPR_PROTOCOL
42 : :
43 : : __BEGIN_NS_SSRC_WSPR_WS
44 : :
45 : : using std::string;
46 : : using NS_SSRC_WISP_PROTOCOL::wisp_call_token;
47 : : using NS_SSRC_WISP_PROTOCOL::MessageInfo;
48 : : using NS_SSRC_WSPR_UTILITY::Properties;
49 : : using NS_SSRC_WSPR_UTILITY::property_vector;
50 : : using NS_SSRC_WSPR_UTILITY::properties_ptr;
51 : : using NS_SSRC_WSPR_UTILITY::properties_unique_ptr;
52 : : using NS_SSRC_WSPR_UTILITY::AppendToContainer;
53 : : using NS_SSRC_WSPR_SESSION::session_ptr;
54 : :
55 : : /** Requires string literal argument. */
56 : : #define WSPR_WS_TYPE(service_base_str) "wspr.ws." service_base_str
57 : :
58 : : inline Properties & set_web_event_header(Properties & properties,
59 : : const string & protocol,
60 : : const string & call)
61 : : {
62 : : properties.set(protocol, "protocol");
63 : : properties.set(call, "call");
64 : : return properties;
65 : : }
66 : :
67 : : inline Properties & set_web_event_header(Properties & properties,
68 : : const string & protocol,
69 : : const string & call,
70 : : const gsid_type gsid)
71 : : {
72 : : properties.set(gsid, "gsid");
73 : : return set_web_event_header(properties, protocol, call);
74 : : }
75 : :
76 : : inline properties_unique_ptr
77 : : web_event(const string & protocol, const string & call) {
78 : : properties_unique_ptr props(new Properties);
79 : : set_web_event_header(*props, protocol, call);
80 : : return props;
81 : : }
82 : :
83 : : inline properties_unique_ptr
84 : : web_event(const string & protocol, const string & call, const gsid_type gsid) {
85 : : properties_unique_ptr props(new Properties);
86 : : set_web_event_header(*props, protocol, call, gsid);
87 : : return props;
88 : : }
89 : :
90 : : inline Properties & web_event_indirect(Properties & properties,
91 : : const string & protocol,
92 : : const string & call)
93 : : {
94 : : return set_web_event_header(properties, protocol, call);
95 : : }
96 : :
97 : : inline Properties & web_event_indirect(Properties & properties,
98 : : const string & protocol,
99 : : const string & call,
100 : : const gsid_type gsid)
101 : : {
102 : : return set_web_event_header(properties, protocol, call, gsid);
103 : : }
104 : :
105 : : inline Properties & web_event_direct(Properties & properties,
106 : : const string & protocol,
107 : : const string & call)
108 : : {
109 : : Properties *node;
110 : : property_vector & v = properties.create_property_vector("wspr", "event");
111 : : v.push_back(node = new Properties);
112 : : return set_web_event_header(*node, protocol, call);
113 : : }
114 : :
115 : : inline Properties & web_event_direct(Properties & properties,
116 : : const string & protocol,
117 : : const string & call,
118 : : const gsid_type gsid)
119 : : {
120 : : Properties *node;
121 : : property_vector & v = properties.create_property_vector("wspr", "event");
122 : : v.push_back(node = new Properties);
123 : : return set_web_event_header(*node, protocol, call, gsid);
124 : : }
125 : :
126 [ + - + - ]: 2 : struct WebServiceCall {
127 : : WISP_IMPORT(NS_SSRC_WSPR_FCGI, parameter_map);
128 : : string call;
129 : : parameter_map parameters;
130 : : session_ptr session;
131 : :
132 [ + - + - ]: 1 : WebServiceCall() { }
133 : :
134 : 1 : WebServiceCall(const string & call,
135 : : const parameter_map & parameters,
136 : : const session_ptr & session = session_ptr()) :
137 [ + - + - ]: 1 : call(call), parameters(parameters), session(session)
138 : 1 : { }
139 : :
140 : : bool is_parameter(const string & param_name) const {
141 : : parameter_map::const_iterator && it = parameters.find(param_name);
142 : :
143 : : if(it == parameters.end())
144 : : return false;
145 : :
146 : : return true;
147 : : }
148 : :
149 : : template<typename param_type>
150 : : bool get_parameter(const string & param_name, param_type & value) const
151 : : SSRC_DECL_THROW(std::bad_cast)
152 : : {
153 : : parameter_map::const_iterator && it = parameters.find(param_name);
154 : :
155 : : if(it == parameters.end())
156 : : return false;
157 : :
158 : : value = utility::string_to<param_type>(it->second);
159 : :
160 : : return true;
161 : : }
162 : :
163 : : template<typename param_type>
164 : : param_type get_parameter(const string & param_name) const
165 : : SSRC_DECL_THROW(std::bad_cast)
166 : : {
167 : : parameter_map::const_iterator && it = parameters.find(param_name);
168 : :
169 : : if(it == parameters.end())
170 : : return param_type();
171 : :
172 : : return utility::string_to<param_type>(it->second);
173 : : }
174 : :
175 : :
176 : : template<typename container_type>
177 : : unsigned int get_parameters(const string & param_name,
178 : : container_type & container) const
179 : : SSRC_DECL_THROW(std::bad_cast)
180 : : {
181 : : WISP_IMPORT_T(container_type, value_type);
182 : : unsigned int count(0);
183 : : std::pair<parameter_map::const_iterator,parameter_map::const_iterator> &&
184 : : range = parameters.equal_range(param_name);
185 : : AppendToContainer<container_type> append(container);
186 : :
187 : : while(range.first != range.second) {
188 : : append(utility::string_to<value_type>(range.first->second));
189 : : ++range.first;
190 : : ++count;
191 : : }
192 : :
193 : : return count;
194 : : }
195 : :
196 : : template<class Archive>
197 : 2 : void serialize(Archive & ar, const unsigned int) {
198 : 2 : ar & call & parameters & session;
199 : 2 : }
200 : : };
201 : :
202 : : template<> inline
203 : : bool WebServiceCall::get_parameter<string>(const string & param_name,
204 : : string & value) const
205 : : {
206 : : parameter_map::const_iterator && it = parameters.find(param_name);
207 : :
208 : : if(it == parameters.end())
209 : : return false;
210 : :
211 : : value = it->second;
212 : :
213 : : return true;
214 : : }
215 : :
216 : : template<> inline
217 : : string WebServiceCall::get_parameter<string>(const string & param_name) const {
218 : : parameter_map::const_iterator && it = parameters.find(param_name);
219 : :
220 : : if(it == parameters.end())
221 : : return string();
222 : :
223 : : return it->second;
224 : : }
225 : :
226 : : #define __WS_DEFINE_CALL_PARAM(r, data, arg) \
227 : : BOOST_PP_TUPLE_ELEM(2, 0, arg) BOOST_PP_TUPLE_ELEM(2, 1, arg);
228 : :
229 : : #define __WS_INIT_CALL_PARAM(r, data, i, arg) \
230 : : 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))))
231 : : // This is for the benefit of client code that wants to define its own
232 : : // macros that add extra functionality to the generated structure.
233 : : #define __WS_CALL_PARAM(name, param_sequence) \
234 : : BOOST_PP_SEQ_FOR_EACH(__WS_DEFINE_CALL_PARAM, _, param_sequence) \
235 : : name (const NS_SSRC_WSPR_WS::WebServiceCall & call) SSRC_DECL_THROW(std::bad_cast) : \
236 : : BOOST_PP_SEQ_FOR_EACH_I(__WS_INIT_CALL_PARAM, call, param_sequence) \
237 : : { } \
238 : :
239 : : #define WS_CALL_PARAM(name, param_sequence) \
240 : : struct name { \
241 : : __WS_CALL_PARAM(name, param_sequence) \
242 : : }
243 : :
244 : : template<typename ws_type, typename param_type> inline
245 : : void ws_call(ws_type * impl,
246 : : void (ws_type::* call_handler)(const WebServiceCall &, const param_type &, const MessageInfo &),
247 : : const WebServiceCall & call,
248 : : const MessageInfo & msginfo)
249 : : {
250 : : #ifdef WSPR_DEBUG
251 : : try {
252 : : #endif
253 : : (impl->*call_handler)(call, param_type(call), msginfo);
254 : : #ifdef WSPR_DEBUG
255 : : } catch(const std::bad_cast & blc) {
256 : : // TODO: log
257 : : std::cerr << "bad parameters for " << call.call << std::endl
258 : : << blc.what() << std::endl;
259 : : for(WebServiceCall::parameter_map::const_iterator it = call.parameters.begin();
260 : : it != call.parameters.end(); ++it)
261 : : {
262 : : std::cerr << it->first << " : " << it->second << std::endl;
263 : : }
264 : : throw;
265 : : }
266 : : #endif
267 : : }
268 : :
269 : : struct WebServiceProtocol :
270 : : public protocol::ServiceProtocol<protocol::WebService>
271 : : {
272 : : WISP_IMPORT(NS_SSRC_WSPR_FCGI, parameter_map);
273 : :
274 : : enum MessageType {
275 : : OneWay,
276 : : TwoWay,
277 : : Response,
278 : : DeliverEvent,
279 : : DeliverEvents
280 : : };
281 : :
282 : : template<MessageType type>
283 : 2 : struct MessageCallBase : public protocol::MessageWebService<type> {
284 : : WebServiceCall call;
285 : :
286 : 1 : MessageCallBase() { }
287 : :
288 : 1 : MessageCallBase(const string & call,
289 : : const parameter_map & parameters,
290 : : const session_ptr & session = session_ptr()) :
291 : 1 : call(call, parameters, session)
292 : 1 : { }
293 : :
294 : : template<class Archive>
295 : 2 : void serialize(Archive & ar, const unsigned int) {
296 : 2 : ar & call;
297 : 2 : }
298 : : };
299 : :
300 : : typedef MessageCallBase<OneWay> MessageOneWay;
301 : : typedef MessageCallBase<TwoWay> MessageTwoWay;
302 : :
303 : : // IMPORTANT: Changes to MessageResponse must be reflected in SWIG binding.
304 : : // SWIG does not automatically handle nested classes, so we have a separate
305 : : // SWIG interface that must be synchronized to this definition.
306 [ + - + - ]: 2 : class MessageResponse : public protocol::MessageWebService<Response> {
307 : : enum Status { Succeeded, Failed, Error };
308 : :
309 : : unsigned int status;
310 : : string status_msg;
311 : :
312 : 0 : void set_status(Status s, const string & msg) {
313 : 0 : status = s;
314 : 0 : status_msg = msg;
315 : 0 : }
316 : :
317 : : public:
318 : : session_ptr session;
319 : : properties_ptr template_data;
320 : :
321 : 1 : explicit MessageResponse(const session_ptr & session = session_ptr()) :
322 : : status(Succeeded), status_msg(), session(session),
323 [ + - + - : 1 : template_data(new Properties)
+ - + - ]
324 : 1 : { }
325 : :
326 : : // template_data must be the result of new Properties or 0.
327 : 1 : explicit MessageResponse(const session_ptr & session,
328 : : Properties * template_data) :
329 : : status(Succeeded), status_msg(), session(session),
330 [ + - + - ]: 1 : template_data(template_data)
331 : 1 : { }
332 : :
333 : : explicit MessageResponse(const session_ptr & session,
334 : : const properties_ptr & template_data) :
335 : : status(Succeeded), status_msg(), session(session),
336 : : template_data(template_data)
337 : : { }
338 : :
339 : : void set_succeeded(const string & msg = ""){
340 : : set_status(Succeeded, msg);
341 : : }
342 : :
343 : : void set_failed(const string & msg = "") {
344 : : set_status(Failed, msg);
345 : : }
346 : :
347 : 0 : void set_error(const string & msg = "") {
348 : 0 : set_status(Error, msg);
349 : 0 : }
350 : :
351 : : bool succeeded() const { return (status == Succeeded); }
352 : :
353 : : bool failed() const { return (status == Failed); }
354 : :
355 : : bool error() const { return (status == Error); }
356 : :
357 : : const string & status_message() const { return status_msg; }
358 : :
359 : : template<class Archive>
360 : 2 : void serialize(Archive & ar, const unsigned int) {
361 : 2 : ar & status & status_msg & session & template_data;
362 : 2 : }
363 : : };
364 : :
365 : :
366 : : // This is for the EventQueue. It should go in a separate protocol.
367 : : static string event_queue_ws_type() {
368 : : return WSPR_WS_TYPE("event");
369 : : }
370 : :
371 : : static string event_queue_ws_group() {
372 : : return WSPR_WS_TYPE("event");
373 : : }
374 : :
375 : : // This is for the EventQueue. It should go in a separate protocol.
376 : : struct MessageDeliverEvent :
377 : : public protocol::MessageWebService<DeliverEvent>
378 : : {
379 : : typedef std::vector<uid_type> key_container;
380 : : key_container keys;
381 : : properties_ptr template_data;
382 : :
383 : : explicit MessageDeliverEvent(Properties * template_data = new Properties) :
384 : : keys(), template_data(template_data)
385 : : { }
386 : :
387 : : explicit MessageDeliverEvent(const properties_ptr & template_data) :
388 : : keys(), template_data(template_data)
389 : : { }
390 : :
391 : : template<class Archive>
392 : : void serialize(Archive & ar, const unsigned int) {
393 : : ar & keys & template_data;
394 : : }
395 : : };
396 : :
397 : : struct MessageDeliverEvents :
398 : : public protocol::MessageWebService<DeliverEvents>
399 : : {
400 : : typedef std::vector<uid_type> key_container;
401 : : typedef std::vector<Properties> event_container;
402 : : key_container keys;
403 : : event_container events;
404 : :
405 : : explicit MessageDeliverEvents(const unsigned int size = 1) :
406 : : keys(), events(size)
407 : : { }
408 : :
409 : : explicit MessageDeliverEvents(event_container && events) :
410 : : keys(), events(events)
411 : : { }
412 : :
413 : : template<class Archive>
414 : : void serialize(Archive & ar, const unsigned int) {
415 : : ar & keys & events;
416 : : }
417 : : };
418 : :
419 : : WISP_ONE_WAY_CALL(caller_type, OneWay);
420 : : WISP_ONE_WAY_CALL(caller_type, Response);
421 : : WISP_ONE_WAY_CALL(caller_type, DeliverEvent);
422 : : WISP_ONE_WAY_CALL(caller_type, DeliverEvents);
423 : :
424 : : WISP_TWO_WAY_CALL(caller_type, TwoWay, Response);
425 : : };
426 : :
427 : : struct WebServiceCallContextOneWay {
428 : : session_ptr session;
429 : :
430 : : WebServiceCallContextOneWay(const session_ptr & session) :
431 : : session(session)
432 : : { }
433 : : };
434 : :
435 : : struct WebServiceCallContextTwoWay : public WebServiceCallContextOneWay {
436 : : wisp_call_token token;
437 : : string sender;
438 : :
439 : : WebServiceCallContextTwoWay(const session_ptr & session,
440 : : const wisp_call_token token,
441 : : const string & sender) :
442 : : WebServiceCallContextOneWay(session), token(token), sender(sender)
443 : : { }
444 : : };
445 : :
446 : : __END_NS_SSRC_WSPR_WS
447 : :
448 : : #endif
|