1f033a95eea1bfb111497d1b3d7abc3673c5e05f
[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         const std::string GetFCPString() const;\r
120 \r
121 private:\r
122 \r
123         std::string m_name;\r
124         std::map<std::string,std::string> m_fields;\r
125 \r
126 };\r
127 \r
128 /**\r
129         \brief An FCP connection to a Freenet node\r
130 */\r
131 class Connection\r
132 {\r
133 public:\r
134         /**\r
135                 \brief Default constructor\r
136         */\r
137         Connection();\r
138         /**\r
139                 \brief Construct connection with an existing socket\r
140 \r
141                 \param sock An existing socket connection to a Freenet node\r
142         */\r
143         Connection(const int sock);\r
144         /**\r
145                 \brief Default constructor\r
146 \r
147                 The deconstructor will close the connection if it is open\r
148         */\r
149         ~Connection();\r
150 \r
151         /**\r
152                 \brief Creates an FCP connection to a Freenet node\r
153 \r
154                 If the instaciated object has an existing connection open, it will be closed.\r
155 \r
156                 \param fcphost The IP Address, hostname, FQDN, or other resolvable name that points to the Freenet node\r
157                 \param fcpport The port that the Freenet node is listening for FCP connections on\r
158                 \return true if the connection was established, false if it was not\r
159         */\r
160         const bool Connect(const std::string &fcphost, const int fcpport);\r
161         /**\r
162                 \brief Checks if the connection is currently connected\r
163 \r
164                 \return true if there is a connection, false if there is not\r
165         */\r
166         const bool IsConnected() const                                                          { return m_socket!=-1; }\r
167         /**\r
168                 \brief Disconnects the connection\r
169 \r
170                 \return always true\r
171         */\r
172         const bool Disconnect();\r
173         \r
174         /**\r
175                 \brief Sends and receives data on the connection\r
176 \r
177                 \param ms Maximum number of milliseconds to wait for the send and receive buffers to become available\r
178                 \return true if the connection remains connected, false if the connection is disconnected\r
179         */\r
180         const bool Update(const unsigned long ms);\r
181 \r
182         /**\r
183                 \brief Checks if an FCP message is ready to be received\r
184 \r
185                 \return true if an FCP message is ready to be received, false otherwise\r
186         */\r
187         const bool MessageReady() const;\r
188         \r
189         /**\r
190                 \brief Gets the number of bytes on the receive buffer\r
191 \r
192                 \return The number of bytes on the receive buffer\r
193         */\r
194         const std::vector<char>::size_type ReceiveBufferSize() const    { return m_receivebuffer.size(); }\r
195         /**\r
196                 \brief Receives an FCP message\r
197                 \r
198                 \param[out] message The FCP message\r
199                 \return true if an FCP message was received, false otherwise\r
200         */\r
201         const bool Receive(Message &message);\r
202         /**\r
203                 \brief Receives raw data\r
204                 \r
205                 The received data is inserted at the end of the supplied vector\r
206 \r
207                 \param[out] data vector to place received data in\r
208                 \param len number of bytes to receive\r
209                 \return true if the bytes were received, false otherwise\r
210         */\r
211         const bool Receive(std::vector<char> &data, const std::vector<char>::size_type len);\r
212         /**\r
213                 \brief Receives raw data\r
214 \r
215                 \param[out] data char array to place received data in\r
216                 \param len number of bytes to receive\r
217                 \return true if the bytes were received, false otherwise\r
218         */\r
219         const bool Receive(char *data, const size_t len);\r
220         /**\r
221                 \brief Discards data on receive buffer\r
222 \r
223                 \param len The number of bytes on the receive buffer to discard\r
224                 \return true if the bytes were discarded, false otherwise\r
225         */\r
226         const bool ReceiveIgnore(const size_t len);\r
227         \r
228         /**\r
229                 \brief Gets the number of bytes waiting to be sent to the node\r
230 \r
231                 \return The number of bytes waiting to be sent to the node\r
232         */\r
233         const std::vector<char>::size_type SendBufferSize() const               { return m_sendbuffer.size(); }\r
234         /**\r
235                 \brief Sends an FCP Message\r
236 \r
237                 \param message The Message to send\r
238                 \return true if the Message was buffered for sending successfully, false otherwise\r
239         */\r
240         const bool Send(const Message &message);\r
241         /**\r
242                 \brief Sends raw data\r
243 \r
244                 \param data A vector of the data to send\r
245                 \return true if the data was buffered for sending successfully, false otherwise\r
246         */\r
247         const bool Send(const std::vector<char> &data);\r
248         /**\r
249                 \brief Sends raw data\r
250 \r
251                 \param data A char array of data to send\r
252                 \param len The number of bytes on the array to send\r
253                 \return true if the data was buffered for sending successfully, false otherwise\r
254         */\r
255         const bool Send(const char *data, const size_t len);\r
256 \r
257         /**\r
258                 \brief Gets the socket identifier of the connection\r
259 \r
260                 \return The socket identifier.  It will be -1 if the socket is invalid.\r
261         */\r
262         const int Socket()                                                                                              { return m_socket; }\r
263         \r
264         /**\r
265                 \brief Waits until the receive buffer contains a specified number of bytes\r
266                 \r
267                 This will continuously call Update until either the specific number of bytes have been received,\r
268                 or the connection becomes disconnected\r
269                 \r
270                 \param ms The number of milliseconds for each call to Update\r
271                 \param len The number of bytes to wait for\r
272                 \return true if the number of bytes is waiting on the receive buffer, false if the connection was closed\r
273         */\r
274         const bool WaitForBytes(const unsigned long ms, const size_t len);\r
275 \r
276 private:\r
277         // can't be copied\r
278         Connection(const Connection &connection);\r
279         Connection &operator=(const Connection &connection);\r
280 \r
281         const bool MessageReady(std::vector<char>::const_iterator &endpos, std::vector<char>::size_type &endlen) const;\r
282         const bool MessageReady(std::vector<char>::iterator &endpos, std::vector<char>::size_type &endlen);\r
283         void Split(const std::string &str, const std::string &separators, std::vector<std::string> &elements);\r
284 \r
285         void DoSend();\r
286         void DoReceive();\r
287 \r
288 #ifdef _WIN32\r
289         static bool m_wsastartup;\r
290 #endif\r
291 \r
292         int m_socket;\r
293         std::vector<char> m_receivebuffer;\r
294         std::vector<char> m_sendbuffer;\r
295         std::vector<char> m_tempbuffer;\r
296         fd_set m_readfs;\r
297         fd_set m_writefs;\r
298         struct timeval m_timeval;\r
299         \r
300 };\r
301 \r
302 }       // namespace\r
303 \r
304 #endif  // _fcpv2_connection_\r