1 #ifndef _spin_udpsocket_h
2 #define _spin_udpsocket_h
4 #include "Details/prologue.h"
5 #include <boost/enable_shared_from_this.hpp>
6 #include <boost/function.hpp>
7 #include <boost/tuple/tuple.hpp>
8 #include <boost/thread/recursive_mutex.hpp>
9 #include <Acari/Attributes.h>
10 #include "Details/Address.h"
23 * Though HTTP doesn't support UDP as a transport layer, some HTTP servers
24 * do like to listen on port 80 UDP as well. Also, a UDP socket was the only
25 * thing still missing to handle most other common protocols and allow
26 * Arachnida to be used as a more general-purpose framework for building
27 * embeddable server software. Hence, this class was added in version 1.3
29 class SPIN_API UDPSocket
: public boost::enable_shared_from_this
< UDPSocket
>, private Acari::Attributes
32 //! Type of the call-back called when errors occur
33 typedef boost::function
< void() > OnErrorCallback
;
34 //! Possible status flags
37 //! All is well - no errors occur
39 //! An error occurred during communication
41 //! Communications are done on this connection - the connection is closed
45 using Acari::Attributes::getAttribute
;
46 using Acari::Attributes::allocateAttribute
;
48 /** Construct from an address and a port to listen on.
49 * If either is not provided, you will not be able to receive data
50 * on this socket unless you send data and the receiving end of the
51 * communication replies to wherever the data came from. (I.e. you
52 * will not be able to serve as a server) */
53 UDPSocket(const Details::Address
& address
= Details::Address(0), unsigned short port
= 0);
56 //! Send a given bunch of data to a given address and port
57 std::size_t send(const Details::Address
& to
, unsigned short port
, const std::vector
< char > & data
);
58 //! Send a given bunch of data to a given address and port
59 std::size_t send(const Details::Address
& to
, unsigned short port
, const std::string
& data
) { return send(to
, port
, std::vector
< char >(data
.begin(), data
.end())); }
60 //! Send a given bunch of data to a given address and port
61 std::size_t send(const Details::Address
& to
, unsigned short port
, const char * data
) { return send(to
, port
, std::string(data
)); }
62 //! Send a given bunch of data to a given address and port
63 template < typename T
>
64 std::size_t send(const Details::Address
& to
, unsigned short port
, const T
& data
) { return send(to
, port
, serialize(data
)); }
66 /** Receive data into a given buffer, with a given time-out.
67 * Returns the data in the peek buffer and clears it, if any. Otherwise,
68 * it will try to read from the socket.
69 * \param buffer the buffer to receive data into. If empty, it will be resized to the amount of data received.
70 * \param timeout the amount of time, in milliseconds, to wait. Infinite by default
71 * \return This function returns a tuple containing the address and port
72 * the data was received from, and the amount of data received.
73 * If you've handed this function an empty vector as a buffer, its
74 * size will be exactly the amount of data received when the function
76 boost::tuple
< Details::Address
, unsigned short, std::size_t > recv(std::vector
< char > & buffer
, unsigned long timeout
= ~0);
77 /** Receive data into a given buffer, with a given time-out.
78 * Unlike recv, this function will store the received data in an internal
79 * buffer which you can clear with clearPeekBuffer, and will
80 * return the same data as long as that buffer has not been cleared.
81 * Recv will also return that same data but will automatically clear
83 * \param buffer the buffer to receive data into.
84 * If empty, it will be resized to the amount of data received.
85 * \param timeout the amount of time, in milliseconds, to wait. Infinite by default
86 * \return This function returns a tuple containing the address and port
87 * the data was received from, and the amount of data received.
88 * If you've handed this function an empty vector as a buffer, its
89 * size will be exactly the amount of data received when the function
91 boost::tuple
< Details::Address
, unsigned short, std::size_t > peek(std::vector
< char > & buffer
, unsigned long timeout
= ~0);
93 //! Clear the internal buffer with peeked data
94 void clearPeekBuffer();
96 //! Check whether there is any data to receive on the socket
101 /** Set a new data handler, which will be called whenever data is ready on the connection.
102 * This allows for asynchronous handling of new data. Behind the scenes, a separate thread
103 * will use select(2) on the connection to wait for data. */
104 void setDataHandler(Handlers::UDPDataHandler
& handler
, OnErrorCallback on_error_callback
= OnErrorCallback());
105 //! Clear the new-data handler, returning to a synchronous mode of operation
106 void clearDataHandler();
109 UDPSocket(const UDPSocket
&);
110 UDPSocket
& operator=(const UDPSocket
&);
114 mutable boost::recursive_mutex fd_lock_
;
116 Handlers::UDPDataHandler
* data_handler_
;
117 boost::recursive_mutex peek_buffer_lock_
;
118 boost::tuple
< Details::Address
, unsigned short, std::size_t, std::vector
< char > > peek_buffer_
;