PageRenderTime 7ms CodeModel.GetById 20ms app.highlight 18ms RepoModel.GetById 2ms app.codeStats 0ms

/src/zmqpp/socket.hpp

https://github.com/murrekatt/zmqpp
C++ Header | 538 lines | 119 code | 57 blank | 362 comment | 15 complexity | 3c75544e57979432b41dd7b2aac8e266 MD5 | raw file
  1/**
  2 * \file
  3 *
  4 * \date   9 Aug 2011
  5 * \author Ben Gray (\@benjamg)
  6 */
  7
  8#ifndef ZMQPP_SOCKET_HPP_
  9#define ZMQPP_SOCKET_HPP_
 10
 11#include <cstring>
 12#include <string>
 13#include <list>
 14
 15#include <zmq.h>
 16
 17#include "compatibility.hpp"
 18
 19#include "socket_types.hpp"
 20#include "socket_options.hpp"
 21#include "signal.hpp"
 22
 23namespace zmqpp
 24{
 25
 26class context;
 27class message;
 28
 29typedef std::string endpoint_t;
 30typedef context     context_t;
 31typedef message     message_t;
 32
 33/*!
 34 * The socket class represents the zmq sockets.
 35 *
 36 * A socket can be bound and/or connected to as many endpoints as required
 37 * with the sole exception of a ::pair socket.
 38 *
 39 * The routing is handled by zmq based on the type set.
 40 *
 41 * The bound side of an inproc connection must occur first and inproc can only
 42 * connect to other inproc sockets of the same context.
 43 *
 44 * This class is c++0x move supporting and cannot be copied.
 45 */
 46class socket
 47{
 48public:
 49	static const int normal;                    /*!< /brief default send type, no flags set */
 50#if (ZMQ_VERSION_MAJOR == 2)
 51	static const int dont_wait;				    /*!< /brief don't block if sending is not currently possible  */
 52#else
 53	static const int dont_wait;					/*!< /brief don't block if sending is not currently possible  */
 54#endif
 55	static const int send_more;					/*!< /brief more parts will follow this one */
 56#ifdef ZMQ_EXPERIMENTAL_LABELS
 57	static const int send_label;				/*!< /brief this message part is an internal zmq label */
 58#endif
 59
 60	/*!
 61	 * Create a socket for a given type.
 62	 *
 63	 * \param context the zmq context under which the socket will live
 64	 * \param type a valid ::socket_type for the socket
 65	 */
 66	socket(context_t const& context, socket_type const type);
 67
 68	/*!
 69	 * This will close any socket still open before returning
 70	 */
 71	~socket();
 72
 73	/*!
 74	 * Get the type of the socket, this works on zmqpp types and not the zmq internal types.
 75	 * Use the socket::get method if you wish to intergoate the zmq internal ones.
 76	 *
 77	 * \return the type of the socket
 78	 */
 79	socket_type type() const { return _type; }
 80
 81	/*!
 82	 * Asynchronously binds to an endpoint.
 83	 *
 84	 * \param endpoint the zmq endpoint to bind to
 85	 */
 86	void bind(endpoint_t const& endpoint);
 87
 88#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
 89	/*!
 90	 * Unbinds from a previously bound endpoint.
 91	 *
 92	 * \param endpoint the zmq endpoint to bind to
 93	 */
 94	void unbind(endpoint_t const& endpoint);
 95#endif
 96
 97	/*!
 98	 * Asynchronously connects to an endpoint.
 99	 * If the endpoint is not inproc then zmq will happily keep trying
100	 * to connect until there is something there.
101	 *
102	 * Inproc sockets must have a valid target already bound before connection
103	 * will work.
104	 *
105	 * \param endpoint the zmq endpoint to connect to
106	 */
107	void connect(endpoint_t const& endpoint);
108
109	/*!
110	 * Asynchronously connects to multiple endpoints.
111	 * If the endpoint is not inproc then zmq will happily keep trying
112	 * to connect until there is something there.
113	 *
114	 * Inproc sockets must have a valid target already bound before connection
115	 * will work.
116	 *
117	 * This is a helper function that wraps the single item connect in a loop
118	 *
119	 * \param connections_begin the starting iterator for zmq endpoints.
120	 * \param connections_end the final iterator for zmq endpoints.
121	 */
122	template<typename InputIterator>
123	void connect(InputIterator const& connections_begin, InputIterator const& connections_end)
124	{
125		for(InputIterator it = connections_begin; it != connections_end; ++it)
126		{
127			connect(*it);
128		}
129	}
130
131
132	/*!
133	 * Disconnects a previously connected endpoint.
134	 *
135	 * \param endpoint the zmq endpoint to disconnect from
136	 */
137#if (ZMQ_VERSION_MAJOR > 3) || ((ZMQ_VERSION_MAJOR == 3) && (ZMQ_VERSION_MINOR >= 2))
138	void disconnect(endpoint_t const& endpoint);
139
140	/*!
141	 * Disconnects from multiple previously connected endpoints.
142	 *
143	 * This is a helper function that wraps the single item disconnect in a loop
144	 *
145	 * \param disconnections_begin the starting iterator for zmq endpoints.
146	 * \param disconnections_end the final iterator for zmq endpoints.
147	 */
148	template<typename InputIterator>
149	void disconnect(InputIterator const& disconnections_begin, InputIterator const& disconnections_end)
150	{
151		for(InputIterator it = disconnections_begin; it != disconnections_end; ++it)
152		{
153			disconnect(*it);
154		}
155	}
156#endif
157
158	/*!
159	 * Closes the internal zmq socket and marks this instance
160	 * as invalid.
161	 */
162	void close();
163
164	/*!
165	 * Sends the message over the connection, this may be a multipart message.
166	 *
167	 * If dont_block is true and we are unable to add a new message then this
168	 * function will return false.
169	 *
170	 * \param message message to send
171	 * \param dont_block boolean to dictate if we wait while sending.
172	 * \return true if message sent, false if it would have blocked
173	 */
174	bool send(message_t& message, bool const dont_block = false);
175
176	/*!
177	 * Gets a message from the connection, this may be a multipart message.
178	 *
179	 * If dont_block is true and we are unable to get a message then this
180	 * function will return false.
181	 *
182	 * \param message reference to fill with received data
183	 * \param dont_block boolean to dictate if we wait for data.
184	 * \return true if message sent, false if it would have blocked
185	 */
186	bool receive(message_t& message, bool const dont_block = false);
187
188	/*!
189	 * Sends the byte data held by the string as the next message part.
190	 *
191	 * If the socket::DONT_WAIT flag and we are unable to add a new message to
192	 * socket then this function will return false.
193	 *
194	 * \param string message part to send
195	 * \param flags message send flags
196	 * \return true if message part sent, false if it would have blocked
197	 */
198	bool send(std::string const& string, int const flags = normal);
199
200	/*!
201	 * If there is a message ready then get the next part as a string
202	 *
203	 * If the socket::DONT_WAIT flag and there is no message ready to receive
204	 * then this function will return false.
205	 *
206	 * \param string message part to receive into
207	 * \param flags message receive flags
208	 * \return true if message part received, false if it would have blocked
209	 */
210	bool receive(std::string& string, int const flags = normal);
211
212	/**
213	 * Sends a signal over the socket.
214	 *
215	 * If the socket::DONT_WAIT flag and we are unable to add a new message to
216	 * socket then this function will return false.
217	 * @param sig signal to send.
218	 * @param flags message send flags
219	 * @return true if message part sent, false if it would have blocked
220	 */
221	bool send(signal sig, int const flags = normal);
222
223
224    	/*!
225	 * If there is a message ready then we read a signal from it.
226	 *
227	 * If the socket::DONT_WAIT flag and there is no message ready to receive
228	 * then this function will return false.
229	 *
230	 * \param sig signal to receive into
231	 * \param flags message receive flags
232	 * \return true if signal received, false if it would have blocked
233	 */
234	bool receive(signal &sig, int const flags = normal);
235
236	/*!
237	 * Sends the byte data pointed to by buffer as the next part of the message.
238	 *
239	 * If the socket::DONT_WAIT flag and we are unable to add a new message to
240	 * socket then this function will return false.
241	 *
242	 * \param buffer byte buffer pointer to start writing from
243	 * \param length max length of the buffer
244	 * \param flags message send flags
245	 * \return true if message part sent, false if it would have blocked
246	 */
247	bool send_raw(char const* buffer, size_t const length, int const flags = normal);
248
249	/*!
250	 * \warning If the buffer is not large enough for the message part then the
251	 *       data will be truncated. The rest of the part is lost forever.
252	 *
253	 * If there is a message ready then get the next part of it as a raw
254	 * byte buffer.
255	 *
256	 * If the socket::DONT_WAIT flag and there is no message ready to receive
257	 * then this function will return false.
258	 *
259	 * \param buffer byte buffer pointer to start writing to
260	 * \param length max length of the buffer
261	 * \param flags message receive flags
262	 * \return true if message part received, false if it would have blocked
263	 */
264	bool receive_raw(char* buffer, size_t& length, int const flags = normal);
265
266	/*!
267	 *
268	 * Subscribe to a topic
269	 *
270	 * Helper function that is equivalent of calling
271	 * \code
272	 * set(zmqpp::socket_option::subscribe, topic);
273	 * \endcode
274	 *
275	 * This method is only useful for subscribe type sockets.
276	 *
277	 * \param topic the topic to subscribe to.
278	 */
279	void subscribe(std::string const& topic);
280
281	/*!
282	 * Subscribe to a topic
283	 *
284	 * Helper function that is equivalent of a loop calling
285	 * \code
286	 * set(zmqpp::socket_option::subscribe, topic);
287	 * \endcode
288	 *
289	 * This method is only useful for subscribe type sockets.
290	 *
291	 * Generally this will be used with stl collections using begin() and
292	 * end() functions to get the iterators.
293	 * For this reason the end loop runs until the end iterator, not inclusive
294	 * of it.
295	 *
296	 * \param topics_begin the starting iterator for topics.
297	 * \param topics_end the final iterator for topics.
298	 */
299	template<typename InputIterator>
300	void subscribe(InputIterator const& topics_begin, InputIterator const& topics_end)
301	{
302		for(InputIterator it = topics_begin; it != topics_end; ++it)
303		{
304			subscribe(*it);
305		}
306	}
307
308	/*!
309	 * Unsubscribe from a topic
310	 *
311	 * Helper function that is equivalent of calling
312	 * \code
313	 * set(zmqpp::socket_option::unsubscribe, topic);
314	 * \endcode
315	 *
316	 * This method is only useful for subscribe type sockets.
317	 *
318	 * \param topic the topic to unsubscribe from.
319	 */
320	void unsubscribe(std::string const& topic);
321
322	/*!
323	 * Unsubscribe from a topic
324	 *
325	 * Helper function that is equivalent of a loop calling
326	 * \code
327	 * set(zmqpp::socket_option::unsubscribe, topic);
328	 * \endcode
329	 *
330	 * This method is only useful for subscribe type sockets.
331	 *
332	 * Generally this will be used with stl collections using begin() and
333	 * end() functions to get the iterators.
334	 * For this reason the end loop runs until the end iterator, not inclusive
335	 * of it.
336	 *
337	 * \param topics_begin the starting iterator for topics.
338	 * \param topics_end the final iterator for topics.
339	 */
340	template<typename InputIterator>
341	void unsubscribe(InputIterator const& topics_begin, InputIterator const& topics_end)
342	{
343		for(InputIterator it = topics_begin; it != topics_end; ++it)
344		{
345			unsubscribe(*it);
346		}
347	}
348
349	/*!
350	 * If the last receive part call to the socket resulted
351	 * in a label or a non-terminating part of a multipart
352	 * message this will return true.
353	 *
354	 * \return true if there are more parts
355	 */
356	bool has_more_parts() const;
357
358	/*!
359	 * Set the value of an option in the underlaying zmq socket.
360	 *
361	 * \param option a valid ::socket_option
362	 * \param value to set the option to
363	 */
364	void set(socket_option const option, int const value);
365
366	/*!
367	 * Set the value of an option in the underlaying zmq socket.
368	 *
369	 * \since 2.0.0 (built against 0mq version 3.1.x or later)
370	 *
371	 * \param option a valid ::socket_option
372	 * \param value to set the option to
373	 */
374	void set(socket_option const option, bool const value);
375
376	/*!
377	 * Set the value of an option in the underlaying zmq socket.
378	 *
379	 * \param option a valid ::socket_option
380	 * \param value to set the option to
381	 */
382	void set(socket_option const option, uint64_t const value);
383
384	/*!
385	 * Set the value of an option in the underlaying zmq socket.
386	 *
387	 * \param option a valid ::socket_option
388	 * \param value to set the option to
389	 */
390	void set(socket_option const option, int64_t const value);
391
392	/*!
393	 * Set the value of an option in the underlaying zmq socket.
394	 *
395	 * \param option a valid ::socket_option
396	 * \param pointer to raw byte value to set the option to
397	 * \param length the size of the raw byte value
398	 */
399	void set(socket_option const option, char const* value, size_t const length);
400
401	/*!
402	 * Set the value of an option in the underlaying zmq socket.
403	 *
404	 * \param option a valid ::socket_option
405	 * \param pointer to null terminated cstring value to set the option to
406	 */
407	inline void set(socket_option const option, char const* value) { set(option, value, strlen(value)); }
408
409	/*!
410	 * Set the value of an option in the underlaying zmq socket.
411	 *
412	 * \param option a valid ::socket_option
413	 * \param value to set the option to
414	 */
415	inline void set(socket_option const option, std::string const value) { set(option, value.c_str(), value.length()); }
416
417	/*!
418	 * Get a socket option from the underlaying zmq socket.
419	 *
420	 * \param option a valid ::socket_option
421	 * \param value referenced int to return value in
422	 */
423	void get(socket_option const option, int& value) const;
424
425	/*!
426	 * Get a socket option from the underlaying zmq socket.
427	 *
428	 * \param option a valid ::socket_option
429	 * \param value referenced bool to return value in
430	 */
431	void get(socket_option const option, bool& value) const;
432
433	/*!
434	 * Get a socket option from the underlaying zmq socket.
435	 *
436	 * \param option a valid ::socket_option
437	 * \param value referenced uint64_t to return value in
438	 */
439	void get(socket_option const option, uint64_t& value) const;
440
441	/*!
442	 * Get a socket option from the underlaying zmq socket.
443	 *
444	 * \param option a valid ::socket_option
445	 * \param value referenced uint64_t to return value in
446	 */
447	void get(socket_option const option, int64_t& value) const;
448
449	/*!
450	 * Get a socket option from the underlaying zmq socket.
451	 *
452	 * \param option a valid ::socket_option
453	 * \param value referenced std::string to return value in
454	 */
455	void get(socket_option const option, std::string& value) const;
456
457	/*!
458	 * For those that don't want to get into a referenced value this templated method
459	 * will return the value instead.
460	 *
461	 * \param option a valid ::socket_option
462	 * \return socket option value
463	 */
464	template<typename Type>
465	Type get(socket_option const option) const
466	{
467		Type value = Type();
468		get(option, value);
469		return value;
470	}
471
472	/**
473	 * Wait on signal, this is useful to coordinate thread.
474	 * Block until a signal is received, and returns the received signal.
475	 *
476	 * Discard everything until something that looks like a signal is received.
477	 * @return the signal.
478	 */
479	signal wait();
480
481	/*!
482	 * Move constructor
483	 *
484	 * Moves the internals of source to this object, there is no guarantee
485	 * that source will be left in a valid state.
486	 *
487	 * This constructor is noexcept and so will not throw exceptions
488	 *
489	 * \param source target socket to steal internals from
490	 */
491	socket(socket&& source) NOEXCEPT;
492
493	/*!
494	 * Move operator
495	 *
496	 * Moves the internals of source to this object, there is no guarantee
497	 * that source will be left in a valid state.
498	 *
499	 * This function is noexcept and so will not throw exceptions
500	 *
501	 * \param source target socket to steal internals from
502	 * \return socket reference to this
503	 */
504	socket& operator=(socket&& source) NOEXCEPT;
505
506	/*!
507	 * Check the socket is still valid
508	 *
509	 * This tests the internal state of the socket.
510	 * If creation failed for some reason or if the move functions were used
511	 * to move the socket internals to another instance this will return false.
512	 *
513	 * \return true if the socket is valid
514	 */
515	operator bool() const;
516
517	/*!
518	 * Access to the raw 0mq context
519	 *
520	 * \return void pointer to the underlying 0mq socket
521	 */
522	operator void*() const;
523
524private:
525	void* _socket;
526	socket_type _type;
527	zmq_msg_t _recv_buffer;
528
529	// No copy
530	socket(socket const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED;
531	socket& operator=(socket const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED;
532
533	void track_message(message_t const&, uint32_t const, bool&);
534};
535
536}
537
538#endif /* ZMQPP_SOCKET_HPP_ */