version 0.3.29
[fms.git] / include / freenet / fcpv2.h
1 /**\r
2 \r
3         \mainpage FCPv2 library\r
4 \r
5         FCPv2 C++ library\r
6         \r
7         link with ws2_32.lib and iphlpapi.lib in Windows\r
8 \r
9 */\r
10 \r
11 /**\r
12         \file fcpv2.h\r
13 */\r
14 \r
15 #ifndef _fcpv2_\r
16 #define _fcpv2_\r
17 \r
18 #include <map>\r
19 #include <vector>\r
20 #include <string>\r
21 \r
22 #ifdef _WIN32\r
23         #include <winsock2.h>\r
24         #include <windows.h>\r
25 #else\r
26         #include <sys/types.h>\r
27         #include <sys/socket.h>\r
28         #include <netinet/in.h>\r
29         #include <arpa/inet.h>\r
30 #endif\r
31 \r
32 /**\r
33         \brief %FCPv2 namespace\r
34 \r
35         This namespace contains the %FCPv2 library\r
36 */\r
37 namespace FCPv2\r
38 {\r
39 \r
40 /**\r
41         \brief An FCP message\r
42 \r
43         FCP Messages are comprised of a name and zero or more field/value pairs.\r
44 */\r
45 class Message\r
46 {\r
47 public:\r
48         /**\r
49                 \brief Default constructor\r
50         */\r
51         Message();\r
52         /**\r
53                 \brief Construct message with a specific name\r
54 \r
55                 \param name The name of the message\r
56         */\r
57         Message(const std::string &name);\r
58         /**\r
59                 \brief Construct message with a specific name and fields\r
60 \r
61                 The number of field/value pairs must match the fieldcount parameter.\r
62 \r
63                 \param name The name of the message\r
64                 \param fieldcount The number of field/value pairs that follow\r
65         */\r
66         Message(const std::string &name, const int fieldcount, ...);\r
67 \r
68         /**\r
69                 \brief Gets the name of the message\r
70 \r
71                 \return The name of the message\r
72         */\r
73         const std::string &GetName() const                                                      { return m_name; }\r
74         /**\r
75                 \brief Sets the name of the message\r
76 \r
77                 \param name The name of the message\r
78         */\r
79         void SetName(const std::string &name)                                           { m_name=name; }\r
80 \r
81         /**\r
82                 \brief Accesses the field/value pairs\r
83 \r
84                 \param field The field to access\r
85                 \return Reference to the value of the field\r
86         */\r
87         std::string &operator[](const std::string &field)                       { return m_fields[field]; }\r
88 \r
89         /**\r
90                 \brief Non-const accessor for field map\r
91 \r
92                 \return field map\r
93         */\r
94         std::map<std::string,std::string> &GetFields()                          { return m_fields; }\r
95         /**\r
96                 \brief Const accessor for field map\r
97 \r
98                 \return field map\r
99         */\r
100         const std::map<std::string,std::string> &GetFields() const      { return m_fields; }\r
101         \r
102         /**\r
103                 \brief Clears the name and fields of the message\r
104         */\r
105         void Clear()                                                                                            { m_name=""; m_fields.clear(); }\r
106         \r
107         const bool operator==(const Message &rhs) const                         { return (m_name==rhs.m_name && m_fields==rhs.m_fields); }\r
108         const bool operator!=(const Message &rhs) const                         { return !(*this==rhs); }\r
109         const bool operator<(const Message &rhs) const                          { return (m_name<rhs.m_name || (m_name==rhs.m_name && m_fields<rhs.m_fields)); }\r
110         const bool operator<=(const Message &rhs) const                         { return (*this==rhs || *this<rhs); }\r
111         const bool operator>(const Message &rhs) const                          { return !(*this<=rhs); }\r
112         const bool operator>=(const Message &rhs) const                         { return !(*this<rhs); }\r
113         \r
114         /**\r
115                 \brief Gets the string representing this message in FCP\r
116 \r
117                 This string is what is actually sent/received from the node through FCP\r
118 \r
119                 \return The FCP message string\r
120         */\r
121         const std::string GetFCPString() const;\r
122 \r
123 private:\r
124 \r
125         std::string m_name;\r
126         std::map<std::string,std::string> m_fields;\r
127 \r
128 };\r
129 \r
130 /**\r
131         \brief An FCP connection to a Freenet node\r
132 */\r
133 class Connection\r
134 {\r
135 public:\r
136         /**\r
137                 \brief Default constructor\r
138         */\r
139         Connection();\r
140         /**\r
141                 \brief Construct connection with an existing socket\r
142 \r
143                 \param sock An existing open socket connection to a Freenet node\r
144         */\r
145         Connection(const int sock);\r
146         /**\r
147                 \brief Default destructor\r
148 \r
149                 The destructor will close the connection if it is open\r
150         */\r
151         ~Connection();\r
152 \r
153         /**\r
154                 \brief Creates an FCP connection to a Freenet node\r
155 \r
156                 If the instaciated object has an existing connection open, it will be closed.\r
157 \r
158                 \param fcphost The IP Address, hostname, FQDN, or other resolvable name that points to the Freenet node\r
159                 \param fcpport The port that the Freenet node is listening for FCP connections on\r
160                 \return true if the connection was established, false if it was not\r
161         */\r
162         const bool Connect(const std::string &fcphost, const int fcpport);\r
163         /**\r
164                 \brief Checks if the connection is currently connected\r
165 \r
166                 \return true if there is a connection, false if there is not\r
167         */\r
168         const bool IsConnected() const                                                          { return m_socket!=-1; }\r
169         /**\r
170                 \brief Disconnects the connection\r
171 \r
172                 \return always true\r
173         */\r
174         const bool Disconnect();\r
175         \r
176         /**\r
177                 \brief Sends and receives data on the connection\r
178 \r
179                 \param ms Maximum number of milliseconds to wait for the send and receive buffers to become available\r
180                 \return true if the connection remains connected, false if the connection is disconnected\r
181         */\r
182         const bool Update(const unsigned long ms);\r
183 \r
184         /**\r
185                 \brief Checks if an FCP message is ready to be received\r
186 \r
187                 \return true if an FCP message is ready to be received, false otherwise\r
188         */\r
189         const bool MessageReady() const;\r
190         \r
191         /**\r
192                 \brief Gets the number of bytes on the receive buffer\r
193 \r
194                 \return The number of bytes on the receive buffer\r
195         */\r
196         const std::vector<char>::size_type ReceiveBufferSize() const    { return m_receivebuffer.size(); }\r
197         /**\r
198                 \brief Receives an FCP message\r
199                 \r
200                 \param[out] message The FCP message\r
201                 \return true if an FCP message was received, false otherwise\r
202         */\r
203         const bool Receive(Message &message);\r
204         /**\r
205                 \brief Receives raw data\r
206                 \r
207                 The received data is inserted at the end of the supplied vector\r
208 \r
209                 \param[out] data vector to place received data in\r
210                 \param len number of bytes to receive\r
211                 \return true if the bytes were received, false otherwise\r
212         */\r
213         const bool Receive(std::vector<char> &data, const std::vector<char>::size_type len);\r
214         /**\r
215                 \brief Receives raw data\r
216 \r
217                 \param[out] data char array to place received data in\r
218                 \param len number of bytes to receive\r
219                 \return true if the bytes were received, false otherwise\r
220         */\r
221         const bool Receive(char *data, const size_t len);\r
222         /**\r
223                 \brief Discards data on receive buffer\r
224 \r
225                 \param len The number of bytes on the receive buffer to discard\r
226                 \return true if the bytes were discarded, false otherwise\r
227         */\r
228         const bool ReceiveIgnore(const size_t len);\r
229         \r
230         /**\r
231                 \brief Gets the number of bytes waiting to be sent to the node\r
232 \r
233                 \return The number of bytes waiting to be sent to the node\r
234         */\r
235         const std::vector<char>::size_type SendBufferSize() const               { return m_sendbuffer.size(); }\r
236         /**\r
237                 \brief Sends an FCP Message\r
238 \r
239                 \param message The Message to send\r
240                 \return true if the Message was buffered for sending successfully, false otherwise\r
241         */\r
242         const bool Send(const Message &message);\r
243         /**\r
244                 \brief Sends raw data\r
245 \r
246                 \param data A vector of the data to send\r
247                 \return true if the data was buffered for sending successfully, false otherwise\r
248         */\r
249         const bool Send(const std::vector<char> &data);\r
250         /**\r
251                 \brief Sends raw data\r
252 \r
253                 \param data A char array of data to send\r
254                 \param len The number of bytes on the array to send\r
255                 \return true if the data was buffered for sending successfully, false otherwise\r
256         */\r
257         const bool Send(const char *data, const size_t len);\r
258 \r
259         /**\r
260                 \brief Gets the socket identifier of the connection\r
261 \r
262                 \return The socket identifier.  It will be -1 if the socket is invalid.\r
263         */\r
264         const int Socket()                                                                                              { return m_socket; }\r
265         \r
266         /**\r
267                 \brief Waits until the receive buffer contains a specified number of bytes\r
268                 \r
269                 This will continuously call Update until either the specific number of bytes have been received,\r
270                 or the connection becomes disconnected.\r
271                 \r
272                 \param ms The number of milliseconds for each call to Update\r
273                 \param len The number of bytes to wait for\r
274                 \return true if the number of bytes is waiting on the receive buffer, false if the connection was closed\r
275         */\r
276         const bool WaitForBytes(const unsigned long ms, const size_t len);\r
277 \r
278 private:\r
279         // can't be copied\r
280         Connection(const Connection &connection);\r
281         Connection &operator=(const Connection &connection);\r
282 \r
283         const bool MessageReady(std::vector<char>::const_iterator &endpos, std::vector<char>::size_type &endlen) const;\r
284         const bool MessageReady(std::vector<char>::iterator &endpos, std::vector<char>::size_type &endlen);\r
285         void Split(const std::string &str, const std::string &separators, std::vector<std::string> &elements);\r
286 \r
287         void DoSend();\r
288         void DoReceive();\r
289 \r
290 #ifdef _WIN32\r
291         static bool m_wsastartup;\r
292 #endif\r
293 \r
294         int m_socket;\r
295         std::vector<char> m_receivebuffer;\r
296         std::vector<char> m_sendbuffer;\r
297         std::vector<char> m_tempbuffer;\r
298         fd_set m_readfs;\r
299         fd_set m_writefs;\r
300         struct timeval m_timeval;\r
301         \r
302 };\r
303 \r
304 }       // namespace\r
305 \r
306 #endif  // _fcpv2_connection_\r