IlluminatiCore /dep/zmqpp/zmqpp/socket.hpp

Language C/C++ Header Lines 501
MD5 Hash f0d5fad1dd2f332d9ecee58117a8bbc2
Repository https://gitlab.com/IlluminatiCore/IlluminatiCore.git View Raw File
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
/**
 * \file
 *
 * \date   9 Aug 2011
 * \author Ben Gray (\@benjamg)
 */

#ifndef ZMQPP_SOCKET_HPP_
#define ZMQPP_SOCKET_HPP_

#include <cstring>
#include <string>
#include <list>

#include <zmq.h>

#include "compatibility.hpp"

#include "socket_types.hpp"
#include "socket_options.hpp"

namespace zmqpp
{

class context;
class message;

typedef std::string endpoint_t;
typedef context     context_t;
typedef message     message_t;

/*!
 * The socket class represents the zmq sockets.
 *
 * A socket can be bound and/or connected to as many endpoints as required
 * with the sole exception of a ::pair socket.
 *
 * The routing is handled by zmq based on the type set.
 *
 * The bound side of an inproc connection must occur first and inproc can only
 * connect to other inproc sockets of the same context.
 *
 * This class is c++0x move supporting and cannot be copied.
 */
class socket
{
public:
	static const int normal;                    /*!< /brief default send type, no flags set */
#if (ZMQ_VERSION_MAJOR == 2)
	static const int dont_wait;				    /*!< /brief don't block if sending is not currently possible  */
#else
	static const int dont_wait;					/*!< /brief don't block if sending is not currently possible  */
#endif
	static const int send_more;					/*!< /brief more parts will follow this one */
#ifdef ZMQ_EXPERIMENTAL_LABELS
	static const int send_label;				/*!< /brief this message part is an internal zmq label */
#endif

	/*!
	 * Create a socket for a given type.
	 *
	 * \param context the zmq context under which the socket will live
	 * \param type a valid ::socket_type for the socket
	 */
	socket(context_t const& context, socket_type const type);

	/*!
	 * This will close any socket still open before returning
	 */
	~socket();

	/*!
	 * Get the type of the socket, this works on zmqpp types and not the zmq internal types.
	 * Use the socket::get method if you wish to intergoate the zmq internal ones.
	 *
	 * \return the type of the socket
	 */
	socket_type type() const { return _type; }

	/*!
	 * Asynchronously binds to an endpoint.
	 *
	 * \param endpoint the zmq endpoint to bind to
	 */
	void bind(endpoint_t const& endpoint);

	/*!
	 * Unbinds from a previously bound endpoint.
	 *
	 * \param endpoint the zmq endpoint to bind to
	 */
	void unbind(endpoint_t const& endpoint);

	/*!
	 * Asynchronously connects to an endpoint.
	 * If the endpoint is not inproc then zmq will happily keep trying
	 * to connect until there is something there.
	 *
	 * Inproc sockets must have a valid target already bound before connection
	 * will work.
	 *
	 * \param endpoint the zmq endpoint to connect to
	 */
	void connect(endpoint_t const& endpoint);

	/*!
	 * Asynchronously connects to multiple endpoints.
	 * If the endpoint is not inproc then zmq will happily keep trying
	 * to connect until there is something there.
	 *
	 * Inproc sockets must have a valid target already bound before connection
	 * will work.
	 *
	 * This is a helper function that wraps the single item connect in a loop
	 *
	 * \param connections_begin the starting iterator for zmq endpoints.
	 * \param connections_end the final iterator for zmq endpoints.
	 */
	template<typename InputIterator>
	void connect(InputIterator const& connections_begin, InputIterator const& connections_end)
	{
		for(InputIterator it = connections_begin; it != connections_end; ++it)
		{
			connect(*it);
		}
	}


	/*!
	 * Disconnects a previously connected endpoint.
	 *
	 * \param endpoint the zmq endpoint to disconnect from
	 */
	void disconnect(endpoint_t const& endpoint);

	/*!
	 * Disconnects from multiple previously connected endpoints.
	 *
	 * This is a helper function that wraps the single item disconnect in a loop
	 *
	 * \param disconnections_begin the starting iterator for zmq endpoints.
	 * \param disconnections_end the final iterator for zmq endpoints.
	 */
	template<typename InputIterator>
	void disconnect(InputIterator const& disconnections_begin, InputIterator const& disconnections_end)
	{
		for(InputIterator it = disconnections_begin; it != disconnections_end; ++it)
		{
			disconnect(*it);
		}
	}

	/*!
	 * Closes the internal zmq socket and marks this instance
	 * as invalid.
	 */
	void close();

	/*!
	 * Sends the message over the connection, this may be a multipart message.
	 *
	 * If dont_block is true and we are unable to add a new message then this
	 * function will return false.
	 *
	 * \param message message to send
	 * \param dont_block boolean to dictate if we wait while sending.
	 * \return true if message sent, false if it would have blocked
	 */
	bool send(message_t& message, bool const dont_block = false);

	/*!
	 * Gets a message from the connection, this may be a multipart message.
	 *
	 * If dont_block is true and we are unable to get a message then this
	 * function will return false.
	 *
	 * \param message reference to fill with received data
	 * \param dont_block boolean to dictate if we wait for data.
	 * \return true if message sent, false if it would have blocked
	 */
	bool receive(message_t& message, bool const dont_block = false);

	/*!
	 * Sends the byte data held by the string as the next message part.
	 *
	 * If the socket::DONT_WAIT flag and we are unable to add a new message to
	 * socket then this function will return false.
	 *
	 * \param string message part to send
	 * \param flags message send flags
	 * \return true if message part sent, false if it would have blocked
	 */
	bool send(std::string const& string, int const flags = normal);

	/*!
	 * If there is a message ready then get the next part as a string
	 *
	 * If the socket::DONT_WAIT flag and there is no message ready to receive
	 * then this function will return false.
	 *
	 * \param string message part to receive into
	 * \param flags message receive flags
	 * \return true if message part received, false if it would have blocked
	 */
	bool receive(std::string& string, int const flags = normal);

	/*!
	 * Sends the byte data pointed to by buffer as the next part of the message.
	 *
	 * If the socket::DONT_WAIT flag and we are unable to add a new message to
	 * socket then this function will return false.
	 *
	 * \param buffer byte buffer pointer to start writing from
	 * \param length max length of the buffer
	 * \param flags message send flags
	 * \return true if message part sent, false if it would have blocked
	 */
	bool send_raw(char const* buffer, int const length, int const flags = normal);

	/*!
	 * \warning If the buffer is not large enough for the message part then the
	 *       data will be truncated. The rest of the part is lost forever.
	 *
	 * If there is a message ready then get the next part of it as a raw
	 * byte buffer.
	 *
	 * If the socket::DONT_WAIT flag and there is no message ready to receive
	 * then this function will return false.
	 *
	 * \param buffer byte buffer pointer to start writing to
	 * \param length max length of the buffer
	 * \param flags message receive flags
	 * \return true if message part received, false if it would have blocked
	 */
	bool receive_raw(char* buffer, int& length, int const flags = normal);

	/*!
	 *
	 * Subscribe to a topic
	 *
	 * Helper function that is equivalent of calling
	 * \code
	 * set(zmqpp::socket_option::subscribe, topic);
	 * \endcode
	 *
	 * This method is only useful for subscribe type sockets.
	 *
	 * \param topic the topic to subscribe to.
	 */
	void subscribe(std::string const& topic);

	/*!
	 * Subscribe to a topic
	 *
	 * Helper function that is equivalent of a loop calling
	 * \code
	 * set(zmqpp::socket_option::subscribe, topic);
	 * \endcode
	 *
	 * This method is only useful for subscribe type sockets.
	 *
	 * Generally this will be used with stl collections using begin() and
	 * end() functions to get the iterators.
	 * For this reason the end loop runs until the end iterator, not inclusive
	 * of it.
	 *
	 * \param topics_begin the starting iterator for topics.
	 * \param topics_end the final iterator for topics.
	 */
	template<typename InputIterator>
	void subscribe(InputIterator const& topics_begin, InputIterator const& topics_end)
	{
		for(InputIterator it = topics_begin; it != topics_end; ++it)
		{
			subscribe(*it);
		}
	}

	/*!
	 * Unsubscribe from a topic
	 *
	 * Helper function that is equivalent of calling
	 * \code
	 * set(zmqpp::socket_option::unsubscribe, topic);
	 * \endcode
	 *
	 * This method is only useful for subscribe type sockets.
	 *
	 * \param topic the topic to unsubscribe from.
	 */
	void unsubscribe(std::string const& topic);

	/*!
	 * Unsubscribe from a topic
	 *
	 * Helper function that is equivalent of a loop calling
	 * \code
	 * set(zmqpp::socket_option::unsubscribe, topic);
	 * \endcode
	 *
	 * This method is only useful for subscribe type sockets.
	 *
	 * Generally this will be used with stl collections using begin() and
	 * end() functions to get the iterators.
	 * For this reason the end loop runs until the end iterator, not inclusive
	 * of it.
	 *
	 * \param topics_begin the starting iterator for topics.
	 * \param topics_end the final iterator for topics.
	 */
	template<typename InputIterator>
	void unsubscribe(InputIterator const& topics_begin, InputIterator const& topics_end)
	{
		for(InputIterator it = topics_begin; it != topics_end; ++it)
		{
			unsubscribe(*it);
		}
	}

	/*!
	 * If the last receive part call to the socket resulted
	 * in a label or a non-terminating part of a multipart
	 * message this will return true.
	 *
	 * \return true if there are more parts
	 */
	bool has_more_parts() const;

	/*!
	 * Set the value of an option in the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value to set the option to
	 */
	void set(socket_option const option, int const value);

	/*!
	 * Set the value of an option in the underlaying zmq socket.
	 *
	 * \since 2.0.0 (built against 0mq version 3.1.x or later)
	 *
	 * \param option a valid ::socket_option
	 * \param value to set the option to
	 */
	void set(socket_option const option, bool const value);

	/*!
	 * Set the value of an option in the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value to set the option to
	 */
	void set(socket_option const option, uint64_t const value);

	/*!
	 * Set the value of an option in the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value to set the option to
	 */
	void set(socket_option const option, int64_t const value);

	/*!
	 * Set the value of an option in the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param pointer to raw byte value to set the option to
	 * \param length the size of the raw byte value
	 */
	void set(socket_option const option, char const* value, size_t const length);

	/*!
	 * Set the value of an option in the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param pointer to null terminated cstring value to set the option to
	 */
	inline void set(socket_option const option, char const* value) { set(option, value, strlen(value)); }

	/*!
	 * Set the value of an option in the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value to set the option to
	 */
	inline void set(socket_option const option, std::string const value) { set(option, value.c_str(), value.length()); }

	/*!
	 * Get a socket option from the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value referenced int to return value in
	 */
	void get(socket_option const option, int& value) const;

	/*!
	 * Get a socket option from the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value referenced bool to return value in
	 */
	void get(socket_option const option, bool& value) const;

	/*!
	 * Get a socket option from the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value referenced uint64_t to return value in
	 */
	void get(socket_option const option, uint64_t& value) const;

	/*!
	 * Get a socket option from the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value referenced uint64_t to return value in
	 */
	void get(socket_option const option, int64_t& value) const;

	/*!
	 * Get a socket option from the underlaying zmq socket.
	 *
	 * \param option a valid ::socket_option
	 * \param value referenced std::string to return value in
	 */
	void get(socket_option const option, std::string& value) const;

	/*!
	 * For those that don't want to get into a referenced value this templated method
	 * will return the value instead.
	 *
	 * \param option a valid ::socket_option
	 * \return socket option value
	 */
	template<typename Type>
	Type get(socket_option const option) const
	{
		Type value = Type();
		get(option, value);
		return value;
	}

	/*!
	 * Move constructor
	 *
	 * Moves the internals of source to this object, there is no guarantee
	 * that source will be left in a valid state.
	 *
	 * This constructor is noexcept and so will not throw exceptions
	 *
	 * \param source target socket to steal internals from
	 */
	socket(socket&& source) NOEXCEPT;

	/*!
	 * Move operator
	 *
	 * Moves the internals of source to this object, there is no guarantee
	 * that source will be left in a valid state.
	 *
	 * This function is noexcept and so will not throw exceptions
	 *
	 * \param source target socket to steal internals from
	 * \return socket reference to this
	 */
	socket& operator=(socket&& source) NOEXCEPT;

	/*!
	 * Check the socket is still valid
	 *
	 * This tests the internal state of the socket.
	 * If creation failed for some reason or if the move functions were used
	 * to move the socket internals to another instance this will return false.
	 *
	 * \return true if the socket is valid
	 */
	operator bool() const;

	/*!
	 * Access to the raw 0mq context
	 *
	 * \return void pointer to the underlying 0mq socket
	 */
	operator void*() const;

private:
	void* _socket;
	socket_type _type;
	zmq_msg_t _recv_buffer;

	// No copy
	socket(socket const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED;
	socket& operator=(socket const&) NOEXCEPT ZMQPP_EXPLICITLY_DELETED;

	void track_message(message_t const&, uint32_t const, bool&);
};

}

#endif /* ZMQPP_SOCKET_HPP_ */
Back to Top