1 #include "../include/global.h"
\r
2 #include "../include/datetime.h"
\r
3 #include "../include/logfile.h"
\r
4 #include "../include/option.h"
\r
5 #include "../include/stringfunctions.h"
\r
6 #include "../include/db/sqlite3db.h"
\r
7 #include "../include/freenet/freenetmasterthread.h"
\r
8 #include "../include/nntp/nntplistener.h"
\r
9 #include "../include/http/httpthread.h"
\r
10 #include "../include/threadcontroller.h"
\r
13 #include <winsock2.h>
\r
20 bool wantshutdown=false;
\r
26 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
28 db->Open("fms.db3");
\r
29 db->SetBusyTimeout(10000); // set timeout to 10 seconds
\r
30 db->Execute("VACUUM;");
\r
32 // TODO remove this - temp fix for problem in 0.1.8
\r
33 db->Execute("DELETE FROM tblMessageBoard WHERE MessageID NOT IN (SELECT MessageID FROM tblMessage);");
\r
35 db->Execute("CREATE TABLE IF NOT EXISTS tblDBVersion(\
\r
40 SQLite3DB::Statement st=db->Prepare("SELECT Major,Minor FROM tblDBVersion;");
\r
42 if(st.RowReturned())
\r
46 st.ResultInt(0,major);
\r
47 st.ResultInt(1,minor);
\r
49 if(major==1 && minor==0)
\r
51 ConvertDB0100To0101();
\r
58 db->Execute("INSERT INTO tblDBVersion(Major,Minor) VALUES(1,1);");
\r
61 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=2;");
\r
63 db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\
\r
64 Option TEXT UNIQUE,\
\r
65 OptionValue TEXT NOT NULL,\
\r
66 OptionDescription TEXT\
\r
69 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
70 LocalIdentityID INTEGER PRIMARY KEY,\
\r
72 PublicKey TEXT UNIQUE,\
\r
73 PrivateKey TEXT UNIQUE,\
\r
74 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
75 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
76 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
77 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
78 LastInsertedIdentity DATETIME,\
\r
79 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
80 LastInsertedPuzzle DATETIME,\
\r
81 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
82 LastInsertedTrustList DATETIME,\
\r
83 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
84 LastInsertedBoardList DATETIME,\
\r
85 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
86 LastInsertedMessageList DATETIME\
\r
89 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\
\r
90 LocalIdentityID INTEGER,\
\r
92 InsertIndex INTEGER\
\r
95 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\
\r
96 LocalIdentityID INTEGER,\
\r
98 InsertIndex INTEGER\
\r
101 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\
\r
102 IdentityID INTEGER,\
\r
104 RequestIndex INTEGER,\
\r
105 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
108 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\
\r
110 LocalIdentityID INTEGER,\
\r
112 InsertIndex INTEGER,\
\r
116 PuzzleSolution TEXT,\
\r
117 FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\
\r
120 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
121 IdentityID INTEGER PRIMARY KEY,\
\r
122 PublicKey TEXT UNIQUE,\
\r
124 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
125 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
126 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
127 DateAdded DATETIME,\
\r
128 LastSeen DATETIME,\
\r
129 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT 50,\
\r
130 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT 50,\
\r
131 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT 50,\
\r
132 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT 50\
\r
135 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\
\r
136 IdentityID INTEGER,\
\r
138 RequestIndex INTEGER,\
\r
139 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
142 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\
\r
143 IdentityID INTEGER,\
\r
145 RequestIndex INTEGER,\
\r
146 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\
\r
153 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\
\r
154 LocalIdentityID INTEGER,\
\r
158 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
161 db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\
\r
162 IdentityID INTEGER,\
\r
163 TargetIdentityID INTEGER,\
\r
164 MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\
\r
165 TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100)\
\r
168 db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\
\r
169 BoardID INTEGER PRIMARY KEY,\
\r
170 BoardName TEXT UNIQUE,\
\r
171 BoardDescription TEXT,\
\r
172 DateAdded DATETIME\
\r
175 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01 12:00:00');");
\r
176 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01 12:00:00');");
\r
177 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01 12:00:00');");
\r
178 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01 12:00:00');");
\r
180 db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\
\r
181 MessageID INTEGER PRIMARY KEY,\
\r
182 IdentityID INTEGER,\
\r
187 MessageUUID TEXT UNIQUE,\
\r
188 ReplyBoardID INTEGER,\
\r
192 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\
\r
193 MessageID INTEGER,\
\r
194 ReplyToMessageUUID TEXT,\
\r
195 ReplyOrder INTEGER\
\r
198 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\
\r
199 MessageID INTEGER,\
\r
203 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\
\r
204 IdentityID INTEGER,\
\r
206 RequestIndex INTEGER,\
\r
207 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
210 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\
\r
211 IdentityID INTEGER,\
\r
213 RequestIndex INTEGER,\
\r
214 FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\
\r
215 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
218 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\
\r
219 LocalIdentityID INTEGER,\
\r
221 InsertIndex INTEGER,\
\r
222 MessageUUID TEXT UNIQUE,\
\r
224 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
227 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\
\r
228 LocalIdentityID INTEGER,\
\r
230 InsertIndex INTEGER,\
\r
231 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
234 db->Execute("CREATE TABLE IF NOT EXISTS tblAdministrationBoard(\
\r
235 BoardID INTEGER UNIQUE,\
\r
236 ModifyLocalMessageTrust INTEGER,\
\r
237 ModifyLocalTrustListTrust INTEGER\
\r
240 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListInserts(\
\r
241 LocalIdentityID INTEGER,\
\r
243 InsertIndex INTEGER,\
\r
244 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
247 db->Execute("CREATE TABLE IF NOT EXISTS tblBoardListRequests(\
\r
248 IdentityID INTEGER,\
\r
250 RequestIndex INTEGER,\
\r
251 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
254 // MessageInserter will insert a record into this temp table which the MessageListInserter will query for and insert a MessageList when needed
\r
255 db->Execute("CREATE TEMPORARY TABLE IF NOT EXISTS tmpMessageListInsert(\
\r
256 LocalIdentityID INTEGER,\
\r
260 // low / high / message count for each board
\r
261 db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \
\r
262 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \
\r
263 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \
\r
264 WHERE MessageID>=0 OR MessageID IS NULL \
\r
265 GROUP BY tblBoard.BoardID;");
\r
267 // calculates peer trust
\r
268 db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \
\r
269 SELECT TargetIdentityID, \
\r
270 ROUND(SUM(MessageTrust*(LocalMessageTrust/100.0))/SUM(LocalMessageTrust/100.0),0) AS 'PeerMessageTrust', \
\r
271 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(LocalTrustListTrust/100.0),0) AS 'PeerTrustListTrust' \
\r
272 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \
\r
273 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \
\r
274 AND ( PeerTrustListTrust IS NULL OR PeerTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinPeerTrustListTrust') ) \
\r
275 GROUP BY TargetIdentityID;");
\r
278 These peer trust calculations are too CPU intensive to be triggers - they were called every time a new trust list was processed
\r
279 All trust levels will now be recalculated every hour in the PeriodicDBMaintenance class
\r
281 // drop existing triggers
\r
282 db->Execute("DROP TRIGGER IF EXISTS trgDeleteOntblPeerTrust;");
\r
283 db->Execute("DROP TRIGGER IF EXISTS trgInsertOntblPeerTrust;");
\r
284 db->Execute("DROP TRIGGER IF EXISTS trgUpdateOntblPeerTrust;");
\r
285 db->Execute("DROP TRIGGER IF EXISTS trgUpdateLocalTrustLevels;");
\r
287 // update PeerTrustLevel when deleting a record from tblPeerTrust
\r
288 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \
\r
291 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID) WHERE IdentityID=old.TargetIdentityID;\
\r
294 // update PeerTrustLevel when inserting a record into tblPeerTrust
\r
295 db->Execute("CREATE TRIGGER IF NOT EXISTS trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \
\r
298 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID) WHERE IdentityID=new.TargetIdentityID;\
\r
301 // update PeerTrustLevel when updating a record in tblPeerTrust
\r
302 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \
\r
305 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=old.TargetIdentityID) WHERE IdentityID=old.TargetIdentityID;\
\r
306 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=new.TargetIdentityID) WHERE IdentityID=new.TargetIdentityID;\
\r
309 // recalculate all Peer TrustLevels when updating Local TrustLevels on tblIdentity - doesn't really need to be all, but rather all identities the updated identity has a trust level for. It's easier to update everyone for now.
\r
310 db->Execute("CREATE TRIGGER IF NOT EXISTS trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \
\r
313 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\
\r
317 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteMessage AFTER DELETE ON tblMessage \
\r
320 DELETE FROM tblMessageBoard WHERE tblMessageBoard.MessageID=old.MessageID;\
\r
321 DELETE FROM tblMessageReplyTo WHERE tblMessageReplyTo.MessageID=old.MessageID;\
\r
324 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteIdentity AFTER DELETE ON tblIdentity \
\r
327 DELETE FROM tblIdentityRequests WHERE IdentityID=old.IdentityID;\
\r
328 DELETE FROM tblIntroductionPuzzleRequests WHERE IdentityID=old.IdentityID;\
\r
329 DELETE FROM tblMessageListRequests WHERE IdentityID=old.IdentityID;\
\r
330 DELETE FROM tblMessageRequests WHERE IdentityID=old.IdentityID;\
\r
331 DELETE FROM tblPeerTrust WHERE IdentityID=old.IdentityID;\
\r
332 DELETE FROM tblTrustListRequests WHERE IdentityID=old.IdentityID;\
\r
335 db->Execute("CREATE TRIGGER IF NOT EXISTS trgDeleteLocalIdentity AFTER DELETE ON tblLocalIdentity \
\r
338 DELETE FROM tblIdentityIntroductionInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
339 DELETE FROM tblIntroductionPuzzleInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
340 DELETE FROM tblLocalIdentityInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
341 DELETE FROM tblMessageInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
342 DELETE FROM tblMessageListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
343 DELETE FROM tblTrustListInserts WHERE LocalIdentityID=old.LocalIdentityID;\
\r
346 // delete introduction puzzles that were half-way inserted
\r
347 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");
\r
349 // delete stale introduction puzzles (2 or more days old)
\r
350 date.SetToGMTime();
\r
351 date.Add(0,0,0,-2);
\r
352 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
353 db->Execute("DELETE FROM tblIntroductionPuzzleRequests WHERE Day<='"+date.Format("%Y-%m-%d")+"';");
\r
355 date.SetToGMTime();
\r
356 // insert SomeDude's public key
\r
357 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@NuBL7aaJ6Cn4fB7GXFb9Zfi8w1FhPyW3oKgU9TweZMw,iXez4j3qCpd596TxXiJgZyTq9o-CElEuJxm~jNNZAuA,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");
\r
358 // insert Shadow Panther's public key
\r
359 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@~mimyB1kmH4f7Cgsd2wM2Qv2NxrZHRMM6IY8~7EWRVQ,fxTKkR0TYhgMYb-vEGAv55sMOxCGD2xhE4ZxWHxdPz4,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");
\r
360 // insert garfield's public key
\r
361 db->Execute("INSERT INTO tblIdentity(PublicKey,DateAdded) VALUES('SSK@T8l1IEGU4-PoASFzgc2GYhIgRzUvZsKdoQWeuLHuTmM,QLxAPfkGis8l5NafNpSCdbxzXhBlu9WL8svcqJw9Mpo,AQACAAE/','"+date.Format("%Y-%m-%d %H:%M:%S")+"');");
\r
365 void ConvertDB0100To0101()
\r
367 // added unique constraint to public and private key
\r
368 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
369 db->Execute("CREATE TEMPORARY TABLE tblLocalIdentityTemp AS SELECT * FROM tblLocalIdentity;");
\r
370 db->Execute("DROP TABLE IF EXISTS tblLocalIdentity;");
\r
371 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
372 LocalIdentityID INTEGER PRIMARY KEY,\
\r
374 PublicKey TEXT UNIQUE,\
\r
375 PrivateKey TEXT UNIQUE,\
\r
376 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
377 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
378 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
379 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
380 LastInsertedIdentity DATETIME,\
\r
381 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
382 LastInsertedPuzzle DATETIME,\
\r
383 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
384 LastInsertedTrustList DATETIME,\
\r
385 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
386 LastInsertedBoardList DATETIME,\
\r
387 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
388 LastInsertedMessageList DATETIME\
\r
390 db->Execute("INSERT INTO tblLocalIdentity SELECT * FROM tblLocalIdentityTemp;");
\r
391 db->Execute("DROP TABLE IF EXISTS tblLocalIdentityTemp;");
\r
392 db->Execute("UPDATE tblDBVersion SET Major=1, Minor=1;");
\r
395 void SetupDefaultOptions()
\r
397 // OptionValue should always be inserted as a string, even if the option really isn't a string - just to keep the field data type consistent
\r
399 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
400 SQLite3DB::DB *db=SQLite3DB::DB::Instance();
\r
401 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
405 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
406 st.Bind(0,"LogLevel");
\r
407 st.Bind(1,tempstr.str());
\r
408 st.Bind(2,"The maximum logging level that will be written to file. 0=Fatal Errors, 1=Errors, 2=Warnings, 3=Informational Messages, 4=Debug Messages. Higher levels will include all messages from the previous levels.");
\r
413 st.Bind(0,"NNTPListenPort");
\r
415 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
419 // NNTPBindAddresses
\r
420 st.Bind(0,"NNTPBindAddresses");
\r
421 st.Bind(1,"localhost");
\r
422 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
426 st.Bind(0,"NNTPAllowPost");
\r
428 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
433 st.Bind(0,"StartNNTP");
\r
435 st.Bind(2,"Start NNTP server.");
\r
439 st.Bind(0,"StartHTTP");
\r
441 st.Bind(2,"Start HTTP server.");
\r
445 st.Bind(0,"HTTPListenPort");
\r
447 st.Bind(2,"Port HTTP server will listen on.");
\r
451 // StartFreenetUpdater
\r
452 st.Bind(0,"StartFreenetUpdater");
\r
454 st.Bind(2,"Start Freenet Updater thread.");
\r
459 st.Bind(0,"FCPHost");
\r
460 st.Bind(1,"127.0.0.1");
\r
461 st.Bind(2,"Host name or address of Freenet node.");
\r
466 st.Bind(0,"FCPPort");
\r
468 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
472 st.Bind(0,"MessageBase");
\r
474 st.Bind(2,"A unique string shared by all clients who want to communicate with each other. This should not be changed unless you want to create your own separate communications network.");
\r
478 st.Bind(0,"MaxIdentityRequests");
\r
480 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
484 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
486 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
490 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
492 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
496 st.Bind(0,"MaxTrustListRequests");
\r
498 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
502 st.Bind(0,"MaxMessageListRequests");
\r
504 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
508 st.Bind(0,"MaxMessageRequests");
\r
510 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
514 st.Bind(0,"MinLocalMessageTrust");
\r
516 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
520 st.Bind(0,"MinPeerMessageTrust");
\r
522 st.Bind(2,"Specifies a peer message trust level that a peer must have before its messages will be downloaded.");
\r
526 st.Bind(0,"MinLocalTrustListTrust");
\r
528 st.Bind(2,"Specifies a local trust list trust level that a peer must have before its trust list will be included in the weighted average. Any peers below this number will be excluded from the results.");
\r
532 st.Bind(0,"MinPeerTrustListTrust");
\r
534 st.Bind(2,"Specifies a peer trust list trust level that a peer must have before its trust list will be included in the weighted average. Any peers below this number will be excluded from the results.");
\r
538 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
540 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
544 st.Bind(0,"MessageListDaysBackward");
\r
546 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
550 st.Bind(0,"MaxPeerMessagesPerDay");
\r
552 st.Bind(2,"The maximum number of messages you will download from each peer on a given day.");
\r
556 st.Bind(0,"MaxBoardListRequests");
\r
558 st.Bind(2,"The maximum number of concurrent requests for new Board Lists. Set to 0 to disable.");
\r
562 st.Bind(0,"MaxBoardsPerMessage");
\r
564 st.Bind(2,"The maximum number of boards a received message may be sent to. Boards over this limit will be ignored.");
\r
570 void SetupLogFile()
\r
573 std::string configval;
\r
576 date.SetToGMTime();
\r
578 LogFile::Instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
579 LogFile::Instance()->OpenFile();
\r
580 LogFile::Instance()->SetWriteNewLine(true);
\r
581 LogFile::Instance()->SetWriteDate(true);
\r
582 LogFile::Instance()->SetWriteLogLevel(true);
\r
584 if(Option::Instance()->Get("LogLevel",configval)==false)
\r
587 Option::Instance()->Set("LogLevel",configval);
\r
589 if(StringFunctions::Convert(configval,loglevel)==false)
\r
591 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
592 Option::Instance()->Set("LogLevel",loglevel);
\r
594 LogFile::Instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
597 void SetupNetwork()
\r
601 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
607 ThreadController::Instance()->ShutdownThreads();
\r
611 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_INFO,"FMS shutdown");
\r
612 LogFile::Instance()->WriteNewLine();
\r
615 void ShutdownNetwork()
\r
622 void SigHandler(int signum)
\r
629 void ShutdownThreads(std::vector<PThread::Thread *> &threads)
\r
631 std::vector<PThread::Thread *>::iterator i;
\r
632 for(i=threads.begin(); i!=threads.end(); i++)
\r
637 for(i=threads.begin(); i!=threads.end(); i++)
\r
639 LogFile::Instance()->WriteLog(LogFile::LOGLEVEL_DEBUG,"ShutdownThreads waiting for thread to exit.");
\r
649 void StartThreads(std::vector<PThread::Thread *> &threads)
\r
651 std::string startfreenet;
\r
652 std::string startnntp;
\r
653 std::string starthttp;
\r
655 if(Option::Instance()->Get("StartFreenetUpdater",startfreenet)==false)
\r
657 startfreenet="true";
\r
658 Option::Instance()->Set("StartFreenetUpdater","true");
\r
661 if(Option::Instance()->Get("StartNNTP",startnntp)==false)
\r
664 Option::Instance()->Set("StartNNTP","true");
\r
667 if(Option::Instance()->Get("StartHTTP",starthttp)==false)
\r
670 Option::Instance()->Set("StartHTTP","true");
\r
673 if(startfreenet=="true")
\r
675 PThread::Thread *t=new PThread::Thread(new FreenetMasterThread());
\r
676 threads.push_back(t);
\r
679 if(startnntp=="true")
\r
681 PThread::Thread *t=new PThread::Thread(new NNTPListener());
\r
682 threads.push_back(t);
\r
685 if(starthttp=="true")
\r
687 PThread::Thread *t=new PThread::Thread(new HTTPThread());
\r
688 threads.push_back(t);
\r