version 0.3.29
[fms.git] / src / freenet / freenetmasterthread.cpp
1 #include "../../include/freenet/freenetmasterthread.h"\r
2 #include "../../include/option.h"\r
3 #include "../../include/stringfunctions.h"\r
4 #include "../../include/freenet/unkeyedidcreator.h"\r
5 #include "../../include/freenet/identityinserter.h"\r
6 #include "../../include/freenet/identityrequester.h"\r
7 #include "../../include/freenet/unknownidentityrequester.h"\r
8 #include "../../include/freenet/introductionpuzzleinserter.h"\r
9 #include "../../include/freenet/identityintroductionrequester.h"\r
10 #include "../../include/freenet/introductionpuzzlerequester.h"\r
11 #include "../../include/freenet/identityintroductioninserter.h"\r
12 #include "../../include/freenet/trustlistinserter.h"\r
13 #include "../../include/freenet/trustlistrequester.h"\r
14 #include "../../include/freenet/messagelistrequester.h"\r
15 #include "../../include/freenet/inactivemessagelistrequester.h"\r
16 #include "../../include/freenet/messagelistinserter.h"\r
17 #include "../../include/freenet/messagerequester.h"\r
18 #include "../../include/freenet/messageinserter.h"\r
19 #include "../../include/freenet/boardlistinserter.h"\r
20 #include "../../include/freenet/boardlistrequester.h"\r
21 #include "../../include/freenet/siteinserter.h"\r
22 #include "../../include/freenet/fileinserter.h"\r
23 #include "../../include/freenet/fmsversionrequester.h"\r
24 \r
25 #include <Poco/UUID.h>\r
26 #include <Poco/UUIDGenerator.h>\r
27 #include <Poco/DateTime.h>\r
28 #include <Poco/Timespan.h>\r
29 #include <Poco/Thread.h>\r
30 \r
31 #include <cstdlib>\r
32 \r
33 #ifdef XMEM\r
34         #include <xmem.h>\r
35 #endif\r
36 \r
37 FreenetMasterThread::FreenetMasterThread():m_receivednodehello(false)\r
38 {\r
39 \r
40 }\r
41 \r
42 FreenetMasterThread::~FreenetMasterThread()\r
43 {\r
44 \r
45 }\r
46 \r
47 const bool FreenetMasterThread::FCPConnect()\r
48 {\r
49         // we were previosly connected, send FCPDisconnect to objects\r
50         if(m_receivednodehello==true)\r
51         {\r
52                 for(std::vector<IFCPConnected *>::iterator i=m_fcpconnected.begin(); i!=m_fcpconnected.end(); i++)\r
53                 {\r
54                         (*i)->FCPDisconnected();\r
55                 }\r
56                 m_receivednodehello=false;\r
57         }\r
58 \r
59         m_log->information("FreenetMasterThread::FCPConnect trying to connect to node "+m_fcphost);\r
60 \r
61         if(m_fcp.Connect(m_fcphost.c_str(),m_fcpport)==true)\r
62         {\r
63                 Poco::UUIDGenerator uuidgen;\r
64                 Poco::UUID uuid;\r
65 \r
66                 try\r
67                 {\r
68                         uuid=uuidgen.createRandom();\r
69                 }\r
70                 catch(...)\r
71                 {\r
72                         m_log->fatal("FreenetMasterThread::FCPConnect could not generate UUID");\r
73                 }\r
74 \r
75                 std::string clientname="FMSClient-"+uuid.toString();\r
76                 // send ClientHello message to node\r
77                 m_fcp.Send(FCPv2::Message("ClientHello",2,"Name",clientname.c_str(),"ExpectedVersion","2.0"));\r
78 \r
79                 m_log->information("FreenetMasterThread::FCPConnect connected to node");\r
80 \r
81                 return true;\r
82         }\r
83         else\r
84         {\r
85                 return false;\r
86         }\r
87 \r
88 }\r
89 \r
90 const bool FreenetMasterThread::HandleMessage(FCPv2::Message &message)\r
91 {\r
92         if(message.GetName()=="NodeHello")\r
93         {\r
94                 m_receivednodehello=true;\r
95 \r
96                 // send connected message to all objects, must do this AFTER we received the NodeHello message\r
97                 for(std::vector<IFCPConnected *>::iterator i=m_fcpconnected.begin(); i!=m_fcpconnected.end(); i++)\r
98                 {\r
99                         (*i)->FCPConnected();\r
100                 }\r
101 \r
102                 return true;\r
103         }\r
104         if(m_receivednodehello==true)\r
105         {\r
106                 bool handled=false;\r
107 \r
108                 std::vector<IFCPMessageHandler *>::iterator i=m_fcpmessagehandlers.begin();\r
109                 while(handled==false && i!=m_fcpmessagehandlers.end())\r
110                 {\r
111                         handled=(*i)->HandleMessage(message);\r
112                         i++;\r
113                 }\r
114 \r
115                 if(handled==false)\r
116                 {\r
117                         std::string info("");\r
118                         for(std::map<std::string,std::string>::iterator mi=message.GetFields().begin(); mi!=message.GetFields().end(); mi++)\r
119                         {\r
120                                 info+="\t\t\t\t"+(*mi).first+"="+(*mi).second+"\r\n";\r
121                         }\r
122                         m_log->debug("FreenetMasterThread::HandleMessage received unhandled "+message.GetName()+" message.  Message content :\r\n"+info);\r
123 \r
124                         // if unhandled message was alldata - we must retrieve the data\r
125                         if(message.GetName()=="AllData")\r
126                         {\r
127                                 long length;\r
128                                 StringFunctions::Convert(message["DataLength"],length);\r
129                                 m_fcp.WaitForBytes(1000,length);\r
130 \r
131                                 if(m_fcp.IsConnected() && length>0)\r
132                                 {\r
133                                         m_fcp.ReceiveIgnore(length);\r
134                                 }\r
135                         }\r
136                 }\r
137 \r
138                 return handled;\r
139 \r
140         }\r
141         else\r
142         {\r
143                 m_log->error("FreenetMasterThread::HandleMessage received "+message.GetName()+" message before NodeHello");\r
144         }\r
145 \r
146         return false;\r
147 }\r
148 \r
149 void FreenetMasterThread::RegisterFCPConnected(IFCPConnected *obj)\r
150 {\r
151         m_fcpconnected.push_back(obj);\r
152 }\r
153 \r
154 void FreenetMasterThread::RegisterFCPMessageHandler(IFCPMessageHandler *obj)\r
155 {\r
156         m_fcpmessagehandlers.push_back(obj);\r
157 }\r
158 \r
159 void FreenetMasterThread::RegisterPeriodicProcessor(IPeriodicProcessor *obj)\r
160 {\r
161         m_processors.push_back(obj);\r
162 }\r
163 \r
164 void FreenetMasterThread::run()\r
165 {\r
166 \r
167         Poco::DateTime lastreceivedmessage;\r
168         Poco::DateTime lastconnected;\r
169         Poco::DateTime now;\r
170         FCPv2::Message message;\r
171         bool done=false;\r
172 \r
173         lastconnected-=Poco::Timespan(0,0,1,0,0);\r
174 \r
175         m_log->debug("FreenetMasterThread::run thread started.");\r
176 \r
177         LoadDatabase();\r
178 \r
179 \r
180 \r
181         Setup();\r
182 \r
183         do\r
184         {\r
185                 try\r
186                 {\r
187                         if(m_fcp.IsConnected()==false)\r
188                         {\r
189                                 // wait at least 1 minute since last successful connect\r
190                                 now=Poco::Timestamp();\r
191                                 if(lastconnected<=(now-Poco::Timespan(0,0,1,0,0)))\r
192                                 {\r
193                                         if(FCPConnect()==false)\r
194                                         {\r
195 \r
196                                                 m_log->error("FreenetMasterThread::run could not connect to node.  Waiting 60 seconds.");\r
197 \r
198                                                 for(int i=0; i<60 && !IsCancelled(); i++)\r
199                                                 {\r
200                                                         Poco::Thread::sleep(1000);\r
201                                                 }\r
202                                         }\r
203                                         else\r
204                                         {\r
205                                                 lastreceivedmessage=Poco::Timestamp();\r
206                                                 lastconnected=Poco::Timestamp();\r
207                                         }\r
208                                 }\r
209                                 else\r
210                                 {\r
211                                         Poco::Thread::sleep(1000);\r
212                                 }\r
213                         }\r
214                         // fcp is connected\r
215                         else\r
216                         {\r
217                                 m_fcp.Update(1000);\r
218 \r
219                                 // check for message on receive buffer and handle it\r
220                                 if(m_fcp.MessageReady()==true)\r
221                                 {\r
222                                         message.Clear();\r
223                                         m_fcp.Receive(message);\r
224 \r
225                                         if(message.GetName()!="")\r
226                                         {\r
227                                                 HandleMessage(message);\r
228                                                 lastreceivedmessage=Poco::Timestamp();\r
229                                         }\r
230                                 }\r
231 \r
232                                 // let objects do their processing\r
233                                 for(std::vector<IPeriodicProcessor *>::iterator i=m_processors.begin(); i!=m_processors.end(); i++)\r
234                                 {\r
235                                         (*i)->Process();\r
236                                 }\r
237 \r
238                                 // if we haven't received any messages from the node in 10 minutes, something is wrong\r
239                                 now=Poco::Timestamp();\r
240                                 if(lastreceivedmessage<(now-Poco::Timespan(0,0,10,0,0)))\r
241                                 {\r
242                                         m_log->error("FreenetMasterThread::Run The Freenet node has not responded in 10 minutes.  Trying to reconnect.");\r
243                                         m_fcp.Disconnect();\r
244                                 }\r
245 \r
246                                 if(m_fcp.IsConnected()==false)\r
247                                 {\r
248                                         m_log->information("FreenetMasterThread::Run Disconnected from Freenet node.");\r
249                                 }\r
250 \r
251                         }\r
252                 }\r
253                 catch(Poco::Exception &e)\r
254                 {\r
255                         m_log->error("FreenetMasterThread::run caught exception : "+e.displayText());\r
256                 }\r
257                 catch(...)\r
258                 {\r
259                         m_log->error("FreenetMasterThread::run caught unknown exception");\r
260                 }\r
261         }while(!IsCancelled() && done==false);\r
262 \r
263         m_fcp.Disconnect();\r
264 \r
265         Shutdown();\r
266 \r
267         m_log->debug("FreenetMasterThread::run thread exiting.");\r
268 \r
269 }\r
270 \r
271 void FreenetMasterThread::Setup()\r
272 {\r
273 \r
274         Option option(m_db);\r
275         if(option.Get("FCPHost",m_fcphost)==false)\r
276         {\r
277                 m_fcphost="localhost";\r
278                 option.Set("FCPHost",m_fcphost);\r
279         }\r
280         if(option.GetInt("FCPPort",m_fcpport)==false)\r
281         {\r
282                 m_fcpport=9481;\r
283                 option.Set("FCPPort",m_fcpport);\r
284         }\r
285         else\r
286         {\r
287                 if(m_fcpport<1 || m_fcpport>65535)\r
288                 {\r
289                         m_fcpport=9481;\r
290                         option.Set("FCPPort",m_fcpport);\r
291                 }\r
292         }\r
293 \r
294         // seed random number generator\r
295         srand(time(NULL));\r
296 \r
297         m_registrables.push_back(new UnkeyedIDCreator(m_db,&m_fcp));\r
298         m_registrables.push_back(new IdentityInserter(m_db,&m_fcp));\r
299         m_registrables.push_back(new IdentityRequester(m_db,&m_fcp));\r
300         m_registrables.push_back(new UnknownIdentityRequester(m_db,&m_fcp));\r
301         m_registrables.push_back(new IntroductionPuzzleInserter(m_db,&m_fcp));\r
302         m_registrables.push_back(new IdentityIntroductionRequester(m_db,&m_fcp));\r
303         m_registrables.push_back(new IntroductionPuzzleRequester(m_db,&m_fcp));\r
304         m_registrables.push_back(new IdentityIntroductionInserter(m_db,&m_fcp));\r
305         m_registrables.push_back(new TrustListInserter(m_db,&m_fcp));\r
306         m_registrables.push_back(new TrustListRequester(m_db,&m_fcp));\r
307         m_registrables.push_back(new MessageListInserter(m_db,&m_fcp));\r
308         m_registrables.push_back(new MessageListRequester(m_db,&m_fcp));\r
309         m_registrables.push_back(new InactiveMessageListRequester(m_db,&m_fcp));\r
310         m_registrables.push_back(new MessageInserter(m_db,&m_fcp));\r
311         m_registrables.push_back(new MessageRequester(m_db,&m_fcp));\r
312         m_registrables.push_back(new BoardListInserter(m_db,&m_fcp));\r
313         m_registrables.push_back(new BoardListRequester(m_db,&m_fcp));\r
314         m_registrables.push_back(new SiteInserter(m_db,&m_fcp));\r
315         m_registrables.push_back(new FileInserter(m_db,&m_fcp));\r
316         m_registrables.push_back(new FMSVersionRequester(m_db,&m_fcp));\r
317 \r
318         for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
319         {\r
320                 (*i)->RegisterWithThread(this);\r
321         }\r
322 \r
323 }\r
324 \r
325 void FreenetMasterThread::Shutdown()\r
326 {\r
327         // delete each registrable object\r
328         for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
329         {\r
330                 delete (*i);\r
331         }\r
332 }\r