Use Vlinder::Atomics
[Arachnida.git] / lib / Spin / UDPSocket.h
blobccdd86d53e777bb06c21b5730fe21bee932362bc
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"
12 namespace Spin
14 namespace Details
16 struct Address;
18 namespace Handlers
20 class UDPDataHandler;
22 /** A UDP socket.
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
28 * of Arachnida. */
29 class SPIN_API UDPSocket : public boost::enable_shared_from_this< UDPSocket >, private Acari::Attributes
31 public :
32 //! Type of the call-back called when errors occur
33 typedef boost::function< void() > OnErrorCallback;
34 //! Possible status flags
35 enum Status
37 //! All is well - no errors occur
38 good__ = 0,
39 //! An error occurred during communication
40 error__ = 1,
41 //! Communications are done on this connection - the connection is closed
42 done__ = 2
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);
54 ~UDPSocket();
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
75 * returns*/
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
82 * the peek buffer.
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
90 * returns*/
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
97 bool poll() const;
98 //! Close the socket.
99 void close();
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();
108 private :
109 UDPSocket(const UDPSocket&);
110 UDPSocket & operator=(const UDPSocket&);
112 void onDataReady_();
114 mutable boost::recursive_mutex fd_lock_;
115 int fd_;
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_;
122 #endif