01f03a083ae8b7d628d5ba86ae9435fa21f01244
[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/introductionpuzzleinserter.h"\r
8 #include "../../include/freenet/identityintroductionrequester.h"\r
9 #include "../../include/freenet/introductionpuzzlerequester.h"\r
10 #include "../../include/freenet/introductionpuzzleremover.h"\r
11 #include "../../include/freenet/identityintroductioninserter.h"\r
12 \r
13 #include <zthread/Thread.h>\r
14 \r
15 #ifdef XMEM\r
16         #include <xmem.h>\r
17 #endif\r
18 \r
19 FreenetMasterThread::FreenetMasterThread()\r
20 {\r
21         std::string fcpport;\r
22 \r
23         if(Option::instance()->Get("FCPHost",m_fcphost)==false)\r
24         {\r
25                 m_fcphost="localhost";\r
26                 Option::instance()->Set("FCPHost",m_fcphost);\r
27         }\r
28         if(Option::instance()->Get("FCPPort",fcpport)==false)\r
29         {\r
30                 fcpport="9481";\r
31                 Option::instance()->Set("FCPPort",fcpport);\r
32         }\r
33 \r
34         // convert fcp port to long, and make sure it's within the valid port range\r
35         if(StringFunctions::Convert(fcpport,m_fcpport)==false)\r
36         {\r
37                 m_fcpport=9481;\r
38                 Option::instance()->Set("FCPPort","9481");\r
39         }\r
40 \r
41         m_receivednodehello=false;\r
42 \r
43 }\r
44 \r
45 FreenetMasterThread::~FreenetMasterThread()\r
46 {\r
47 \r
48 }\r
49 \r
50 const bool FreenetMasterThread::FCPConnect()\r
51 {\r
52         // we were previosly connected, send FCPDisconnect to objects\r
53         if(m_receivednodehello==true)\r
54         {\r
55                 for(std::vector<IFCPConnected *>::iterator i=m_fcpconnected.begin(); i!=m_fcpconnected.end(); i++)\r
56                 {\r
57                         (*i)->FCPDisconnected();\r
58                 }\r
59                 m_receivednodehello=false;\r
60         }\r
61 \r
62         m_log->WriteLog(LogFile::LOGLEVEL_INFO,__FUNCTION__" trying to connect to node "+m_fcphost);\r
63 \r
64         if(m_fcp.Connect(m_fcphost.c_str(),m_fcpport)==true)\r
65         {\r
66                 // send ClientHello message to node\r
67                 m_fcp.SendMessage("ClientHello",2,"Name","FMSClient","ExpectedVersion","2.0");\r
68 \r
69                 m_log->WriteLog(LogFile::LOGLEVEL_INFO,__FUNCTION__" connected to node");\r
70 \r
71                 return true;\r
72         }\r
73         else\r
74         {\r
75                 return false;\r
76         }\r
77 \r
78 }\r
79 \r
80 const bool FreenetMasterThread::HandleMessage(FCPMessage &message)\r
81 {\r
82         if(message.GetName()=="NodeHello")\r
83         {\r
84                 m_receivednodehello=true;\r
85 \r
86                 // send connected message to all objects, must do this AFTER we received the NodeHello message\r
87                 for(std::vector<IFCPConnected *>::iterator i=m_fcpconnected.begin(); i!=m_fcpconnected.end(); i++)\r
88                 {\r
89                         (*i)->FCPConnected();\r
90                 }\r
91 \r
92                 return true;\r
93         }\r
94         if(m_receivednodehello==true)\r
95         {\r
96                 bool handled=false;\r
97                 std::vector<IFCPMessageHandler *>::iterator i=m_fcpmessagehandlers.begin();\r
98                 while(handled==false && i!=m_fcpmessagehandlers.end())\r
99                 {\r
100                         handled=(*i)->HandleMessage(message);\r
101                         i++;\r
102                 }\r
103 \r
104                 if(handled==false)\r
105                 {\r
106                         std::string info("");\r
107                         for(std::map<std::string,std::string>::iterator mi=message.begin(); mi!=message.end(); mi++)\r
108                         {\r
109                                 info+="\t\t\t\t"+(*mi).first+"="+(*mi).second+"\r\n";\r
110                         }\r
111                         m_log->WriteLog(LogFile::LOGLEVEL_DEBUG,__FUNCTION__" received unhandled "+message.GetName()+" message.  Message content :\r\n"+info);\r
112 \r
113                         // if unhandled message was alldata - we must retrieve the data\r
114                         if(message.GetName()=="AllData")\r
115                         {\r
116                                 long length;\r
117                                 StringFunctions::Convert(message["DataLength"],length);\r
118                                 while(m_fcp.Connected() && m_fcp.ReceiveBufferSize()<length)\r
119                                 {\r
120                                         m_fcp.Update(1);\r
121                                 }\r
122                                 if(m_fcp.Connected())\r
123                                 {\r
124                                         char *data=new char[length];\r
125                                         m_fcp.ReceiveRaw(data,length);\r
126                                         delete [] data;\r
127                                 }\r
128                         }\r
129                 }\r
130 \r
131                 return handled;\r
132 \r
133         }\r
134         else\r
135         {\r
136                 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,__FUNCTION__" received "+message.GetName()+" message before NodeHello");\r
137         }\r
138 \r
139         return false;\r
140 }\r
141 \r
142 void FreenetMasterThread::RegisterFCPConnected(IFCPConnected *obj)\r
143 {\r
144         m_fcpconnected.push_back(obj);\r
145 }\r
146 \r
147 void FreenetMasterThread::RegisterFCPMessageHandler(IFCPMessageHandler *obj)\r
148 {\r
149         m_fcpmessagehandlers.push_back(obj);\r
150 }\r
151 \r
152 void FreenetMasterThread::RegisterPeriodicProcessor(IPeriodicProcessor *obj)\r
153 {\r
154         m_processors.push_back(obj);\r
155 }\r
156 \r
157 void FreenetMasterThread::run()\r
158 {\r
159 \r
160         FCPMessage message;\r
161         bool done=false;\r
162 \r
163         Setup();\r
164 \r
165         do\r
166         {\r
167                 if(m_fcp.Connected()==false)\r
168                 {\r
169                         if(FCPConnect()==false)\r
170                         {\r
171 \r
172                                 m_log->WriteLog(LogFile::LOGLEVEL_ERROR,__FUNCTION__" could not connect to node.  Waiting 60 seconds.");\r
173 \r
174                                 // wait 60 seconds - will then try to connect again\r
175                                 try\r
176                                 {\r
177                                         ZThread::Thread::sleep(60000);\r
178                                 }\r
179                                 catch(...)\r
180                                 {\r
181                                         done=true;\r
182                                 }\r
183                         }\r
184                 }\r
185                 // fcp is connected\r
186                 else\r
187                 {\r
188                         m_fcp.Update(1);\r
189 \r
190                         // check for message on receive buffer and handle it\r
191                         if(m_fcp.ReceiveBufferSize()>0)\r
192                         {\r
193                                 message.Reset();\r
194                                 message=m_fcp.ReceiveMessage();\r
195 \r
196                                 if(message.GetName()!="")\r
197                                 {\r
198                                         HandleMessage(message);\r
199                                 }\r
200                         }\r
201 \r
202                         // let objects do their processing\r
203                         for(std::vector<IPeriodicProcessor *>::iterator i=m_processors.begin(); i!=m_processors.end(); i++)\r
204                         {\r
205                                 (*i)->Process();\r
206                         }\r
207 \r
208                 }\r
209         }while(!ZThread::Thread::interrupted() && done==false);\r
210 \r
211         m_fcp.Disconnect();\r
212 \r
213         Shutdown();\r
214 \r
215 }\r
216 \r
217 void FreenetMasterThread::Setup()\r
218 {\r
219 \r
220         // seed random number generator\r
221         srand(time(NULL));\r
222 \r
223         m_registrables.push_back(new UnkeyedIDCreator(&m_fcp));\r
224         m_registrables.push_back(new IdentityInserter(&m_fcp));\r
225         m_registrables.push_back(new IdentityRequester(&m_fcp));\r
226         m_registrables.push_back(new IntroductionPuzzleInserter(&m_fcp));\r
227         m_registrables.push_back(new IdentityIntroductionRequester(&m_fcp));\r
228         m_registrables.push_back(new IntroductionPuzzleRequester(&m_fcp));\r
229         m_registrables.push_back(new IntroductionPuzzleRemover());\r
230         m_registrables.push_back(new IdentityIntroductionInserter(&m_fcp));\r
231 \r
232         for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
233         {\r
234                 (*i)->RegisterWithThread(this);\r
235         }\r
236 \r
237 }\r
238 \r
239 void FreenetMasterThread::Shutdown()\r
240 {\r
241         // delete each registerable object\r
242         for(std::vector<IFreenetRegistrable *>::iterator i=m_registrables.begin(); i!=m_registrables.end(); i++)\r
243         {\r
244                 delete (*i);\r
245         }\r
246 }