db72906be498ae8c96321d5ce8d0b9288dce334f
[fms.git] / src / freenet / freenetmasterthread.cpp
1 #include "../../include/freenet/freenetmasterthread.h"\r
2 #include "../../include/option.h"\r
3 #include "../../include/uuidgenerator.h"\r
4 #include "../../include/stringfunctions.h"\r
5 #include "../../include/freenet/unkeyedidcreator.h"\r
6 #include "../../include/freenet/identityinserter.h"\r
7 #include "../../include/freenet/identityrequester.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/messagerequester.h"\r
16 #include "../../include/freenet/messageinserter.h"\r
17 #include "../../include/freenet/messagelistinserter.h"\r
18 #include "../../include/freenet/periodicdbmaintenance.h"\r
19 #include "../../include/freenet/boardlistinserter.h"\r
20 #include "../../include/freenet/boardlistrequester.h"\r
21 #include "../../include/freenet/siteinserter.h"\r
22 \r
23 #include "../../include/pthreadwrapper/thread.h"\r
24 \r
25 #ifdef XMEM\r
26         #include <xmem.h>\r
27 #endif\r
28 \r
29 FreenetMasterThread::FreenetMasterThread()\r
30 {\r
31         std::string fcpport;\r
32 \r
33         if(Option::Instance()->Get("FCPHost",m_fcphost)==false)\r
34         {\r
35                 m_fcphost="localhost";\r
36                 Option::Instance()->Set("FCPHost",m_fcphost);\r
37         }\r
38         if(Option::Instance()->Get("FCPPort",fcpport)==false)\r
39         {\r
40                 fcpport="9481";\r
41                 Option::Instance()->Set("FCPPort",fcpport);\r
42         }\r
43 \r
44         // convert fcp port to long, and make sure it's within the valid port range\r
45         if(StringFunctions::Convert(fcpport,m_fcpport)==false)\r
46         {\r
47                 m_fcpport=9481;\r
48                 Option::Instance()->Set("FCPPort","9481");\r
49         }\r
50 \r
51         m_receivednodehello=false;\r
52 \r
53 }\r
54 \r
55 FreenetMasterThread::~FreenetMasterThread()\r
56 {\r
57 \r
58 }\r
59 \r
60 const bool FreenetMasterThread::FCPConnect()\r
61 {\r
62         // we were previosly connected, send FCPDisconnect to objects\r
63         if(m_receivednodehello==true)\r
64         {\r
65                 for(std::vector<IFCPConnected *>::iterator i=m_fcpconnected.begin(); i!=m_fcpconnected.end(); i++)\r
66                 {\r
67                         (*i)->FCPDisconnected();\r
68                 }\r
69                 m_receivednodehello=false;\r
70         }\r
71 \r
72         m_log->WriteLog(LogFile::LOGLEVEL_INFO,"FreenetMasterThread::FCPConnect trying to connect to node "+m_fcphost);\r
73 \r
74         if(m_fcp.Connect(m_fcphost.c_str(),m_fcpport)==true)\r
75         {\r
76                 UUIDGenerator uuid;\r
77                 std::string clientname="FMSClient-"+uuid.Generate();\r
78                 // send ClientHello message to node\r
79                 m_fcp.SendMessage("ClientHello",2,"Name",clientname.c_str(),"ExpectedVersion","2.0");\r
80 \r
81                 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"FreenetMasterThread::FCPConnect connected to node");\r
82 \r
83                 return true;\r
84         }\r
85         else\r
86         {\r
87                 return false;\r
88         }\r
89 \r
90 }\r
91 \r
92 const bool FreenetMasterThread::HandleMessage(FCPMessage &message)\r
93 {\r
94         if(message.GetName()=="NodeHello")\r
95         {\r
96                 m_receivednodehello=true;\r
97 \r
98                 // send connected message to all objects, must do this AFTER we received the NodeHello message\r
99                 for(std::vector<IFCPConnected *>::iterator i=m_fcpconnected.begin(); i!=m_fcpconnected.end(); i++)\r
100                 {\r
101                         (*i)->FCPConnected();\r
102                 }\r
103 \r
104                 return true;\r
105         }\r
106         if(m_receivednodehello==true)\r
107         {\r
108                 bool handled=false;\r
109                 std::vector<IFCPMessageHandler *>::iterator i=m_fcpmessagehandlers.begin();\r
110                 while(handled==false && i!=m_fcpmessagehandlers.end())\r
111                 {\r
112                         handled=(*i)->HandleMessage(message);\r
113                         i++;\r
114                 }\r
115 \r
116                 if(handled==false)\r
117                 {\r
118                         std::string info("");\r
119                         for(std::map<std::string,std::string>::iterator mi=message.begin(); mi!=message.end(); mi++)\r
120                         {\r
121                                 info+="\t\t\t\t"+(*mi).first+"="+(*mi).second+"\r\n";\r
122                         }\r
123                         m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"FreenetMasterThread::HandleMessage received unhandled "+message.GetName()+" message.  Message content :\r\n"+info);\r
124 \r
125                         // if unhandled message was alldata - we must retrieve the data\r
126                         if(message.GetName()=="AllData")\r
127                         {\r
128                                 long length;\r
129                                 StringFunctions::Convert(message["DataLength"],length);\r
130                                 while(m_fcp.Connected() && m_fcp.ReceiveBufferSize()<length)\r
131                                 {\r
132                                         m_fcp.Update(1);\r
133                                 }\r
134                                 if(m_fcp.Connected())\r
135                                 {\r
136                                         char *data=new char[length];\r
137                                         m_fcp.ReceiveRaw(data,length);\r
138                                         delete [] data;\r
139                                 }\r
140                         }\r
141                 }\r
142 \r
143                 return handled;\r
144 \r
145         }\r
146         else\r
147         {\r
148                 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,"FreenetMasterThread::HandleMessage received "+message.GetName()+" message before NodeHello");\r
149         }\r
150 \r
151         return false;\r
152 }\r
153 \r
154 void FreenetMasterThread::RegisterFCPConnected(IFCPConnected *obj)\r
155 {\r
156         m_fcpconnected.push_back(obj);\r
157 }\r
158 \r
159 void FreenetMasterThread::RegisterFCPMessageHandler(IFCPMessageHandler *obj)\r
160 {\r
161         m_fcpmessagehandlers.push_back(obj);\r
162 }\r
163 \r
164 void FreenetMasterThread::RegisterPeriodicProcessor(IPeriodicProcessor *obj)\r
165 {\r
166         m_processors.push_back(obj);\r
167 }\r
168 \r
169 void FreenetMasterThread::Run()\r
170 {\r
171 \r
172         DateTime lastreceivedmessage;\r
173         DateTime lastconnected;\r
174         DateTime now;\r
175         FCPMessage message;\r
176         bool done=false;\r
177 \r
178         lastconnected.SetToGMTime();\r
179         lastconnected.Add(0,-1);\r
180 \r
181         m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"FreenetMasterThread::run thread started.");\r
182 \r
183         Setup();\r
184 \r
185         do\r
186         {\r
187                 if(m_fcp.Connected()==false)\r
188                 {\r
189                         // wait at least 1 minute since last successful connect\r
190                         now.SetToGMTime();\r
191                         if(lastconnected<=(now-(1.0/1440.0)))\r
192                         {\r
193                                 if(FCPConnect()==false)\r
194                                 {\r
195 \r
196                                         m_log->WriteLog(LogFile::LOGLEVEL_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                                                 Sleep(1000);\r
201                                         }\r
202                                 }\r
203                                 else\r
204                                 {\r
205                                         lastreceivedmessage.SetToGMTime();\r
206                                         lastconnected.SetToGMTime();\r
207                                 }\r
208                         }\r
209                         else\r
210                         {\r
211                                 Sleep(1000);\r
212                         }\r
213                 }\r
214                 // fcp is connected\r
215                 else\r
216                 {\r
217                         m_fcp.Update(1);\r
218 \r
219                         // check for message on receive buffer and handle it\r
220                         if(m_fcp.ReceiveBufferSize()>0)\r
221                         {\r
222                                 message.Reset();\r
223                                 message=m_fcp.ReceiveMessage();\r
224 \r
225                                 if(message.GetName()!="")\r
226                                 {\r
227                                         HandleMessage(message);\r
228                                         lastreceivedmessage.SetToGMTime();\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.SetToGMTime();\r
240                         if(lastreceivedmessage<(now-(1.0/144.0)))\r
241                         {\r
242                                 m_log->WriteLog(LogFile::LOGLEVEL_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.Connected()==false)\r
247                         {\r
248                                 m_log->WriteLog(LogFile::LOGLEVEL_INFO,"FreenetMasterThread::Run Disconnected from Freenet node.");\r
249                         }\r
250 \r
251                 }\r
252         }while(!IsCancelled() && done==false);\r
253 \r
254         m_fcp.Disconnect();\r
255 \r
256         Shutdown();\r
257 \r
258         m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,"FreenetMasterThread::run thread exiting.");\r
259 \r
260 }\r
261 \r
262 void FreenetMasterThread::Setup()\r
263 {\r
264 \r
265         // seed random number generator\r
266         srand(time(NULL));\r
267 \r
268         m_registrables.push_back(new UnkeyedIDCreator(&m_fcp));\r
269         m_registrables.push_back(new IdentityInserter(&m_fcp));\r
270         m_registrables.push_back(new IdentityRequester(&m_fcp));\r
271         m_registrables.push_back(new IntroductionPuzzleInserter(&m_fcp));\r
272         m_registrables.push_back(new IdentityIntroductionRequester(&m_fcp));\r
273         m_registrables.push_back(new IntroductionPuzzleRequester(&m_fcp));\r
274         m_registrables.push_back(new IdentityIntroductionInserter(&m_fcp));\r
275         m_registrables.push_back(new TrustListInserter(&m_fcp));\r
276         m_registrables.push_back(new TrustListRequester(&m_fcp));\r
277         m_registrables.push_back(new MessageListInserter(&m_fcp));\r
278         m_registrables.push_back(new MessageListRequester(&m_fcp));\r
279         m_registrables.push_back(new MessageRequester(&m_fcp));\r
280         m_registrables.push_back(new MessageInserter(&m_fcp));\r
281         m_registrables.push_back(new BoardListInserter(&m_fcp));\r
282         m_registrables.push_back(new BoardListRequester(&m_fcp));\r
283         m_registrables.push_back(new SiteInserter(&m_fcp));\r
284         m_registrables.push_back(new PeriodicDBMaintenance());\r
285 \r
286         for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
287         {\r
288                 (*i)->RegisterWithThread(this);\r
289         }\r
290 \r
291 }\r
292 \r
293 void FreenetMasterThread::Shutdown()\r
294 {\r
295         // delete each registrable object\r
296         for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
297         {\r
298                 delete (*i);\r
299         }\r
300 }\r