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
11 #include <winsock2.h>
\r
21 SQLite3DB::DB *db=SQLite3DB::DB::instance();
\r
23 db->Open("fms.db3");
\r
24 db->SetBusyTimeout(10000); // set timeout to 10 seconds
\r
25 db->Execute("VACUUM;");
\r
27 db->Execute("CREATE TABLE IF NOT EXISTS tblOption(\
\r
28 Option TEXT UNIQUE,\
\r
29 OptionValue TEXT NOT NULL,\
\r
30 OptionDescription TEXT\
\r
33 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentity(\
\r
34 LocalIdentityID INTEGER PRIMARY KEY,\
\r
38 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
39 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
40 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
41 InsertingIdentity BOOL CHECK(InsertingIdentity IN('true','false')) DEFAULT 'false',\
\r
42 LastInsertedIdentity DATETIME,\
\r
43 InsertingPuzzle BOOL CHECK(InsertingPuzzle IN('true','false')) DEFAULT 'false',\
\r
44 LastInsertedPuzzle DATETIME,\
\r
45 InsertingTrustList BOOL CHECK(InsertingTrustList IN('true','false')) DEFAULT 'false',\
\r
46 LastInsertedTrustList DATETIME,\
\r
47 InsertingBoardList BOOL CHECK(InsertingBoardList IN('true','false')) DEFAULT 'false',\
\r
48 LastInsertedBoardList DATETIME,\
\r
49 InsertingMessageList BOOL CHECK(InsertingMessageList IN('true','false')) DEFAULT 'false',\
\r
50 LastInsertedMessageList DATETIME\
\r
53 db->Execute("CREATE TABLE IF NOT EXISTS tblLocalIdentityInserts(\
\r
54 LocalIdentityID INTEGER,\
\r
56 InsertIndex INTEGER\
\r
59 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListInserts(\
\r
60 LocalIdentityID INTEGER,\
\r
62 InsertIndex INTEGER\
\r
65 db->Execute("CREATE TABLE IF NOT EXISTS tblTrustListRequests(\
\r
66 IdentityID INTEGER,\
\r
68 RequestIndex INTEGER,\
\r
69 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
72 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleInserts(\
\r
74 LocalIdentityID INTEGER,\
\r
76 InsertIndex INTEGER,\
\r
80 PuzzleSolution TEXT,\
\r
81 FoundSolution BOOL CHECK(FoundSolution IN('true','false')) DEFAULT 'false'\
\r
84 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentity(\
\r
85 IdentityID INTEGER PRIMARY KEY,\
\r
88 SingleUse BOOL CHECK(SingleUse IN('true','false')) DEFAULT 'false',\
\r
89 PublishTrustList BOOL CHECK(PublishTrustList IN('true','false')) DEFAULT 'false',\
\r
90 PublishBoardList BOOL CHECK(PublishBoardList IN('true','false')) DEFAULT 'false',\
\r
91 DateAdded DATETIME,\
\r
93 LocalMessageTrust INTEGER CHECK(LocalMessageTrust BETWEEN 0 AND 100) DEFAULT 50,\
\r
94 PeerMessageTrust INTEGER CHECK(PeerMessageTrust BETWEEN 0 AND 100) DEFAULT 50,\
\r
95 LocalTrustListTrust INTEGER CHECK(LocalTrustListTrust BETWEEN 0 AND 100) DEFAULT 50,\
\r
96 PeerTrustListTrust INTEGER CHECK(PeerTrustListTrust BETWEEN 0 AND 100) DEFAULT 50\
\r
99 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityRequests(\
\r
100 IdentityID INTEGER,\
\r
102 RequestIndex INTEGER,\
\r
103 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
106 db->Execute("CREATE TABLE IF NOT EXISTS tblIntroductionPuzzleRequests(\
\r
107 IdentityID INTEGER,\
\r
109 RequestIndex INTEGER,\
\r
110 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false',\
\r
117 db->Execute("CREATE TABLE IF NOT EXISTS tblIdentityIntroductionInserts(\
\r
118 LocalIdentityID INTEGER,\
\r
122 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
125 db->Execute("CREATE TABLE IF NOT EXISTS tblPeerTrust(\
\r
126 IdentityID INTEGER,\
\r
127 TargetIdentityID INTEGER,\
\r
128 MessageTrust INTEGER CHECK(MessageTrust BETWEEN 0 AND 100),\
\r
129 TrustListTrust INTEGER CHECK(TrustListTrust BETWEEN 0 AND 100)\
\r
132 db->Execute("CREATE TABLE IF NOT EXISTS tblBoard(\
\r
133 BoardID INTEGER PRIMARY KEY,\
\r
134 BoardName TEXT UNIQUE,\
\r
135 BoardDescription TEXT,\
\r
136 DateAdded DATETIME\
\r
139 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('fms','Freenet Message System','2007-12-01');");
\r
140 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('freenet','Discussion about Freenet','2007-12-01');");
\r
141 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('public','Public discussion','2007-12-01');");
\r
142 db->Execute("INSERT INTO tblBoard(BoardName,BoardDescription,DateAdded) VALUES('test','Test board','2007-12-01');");
\r
144 db->Execute("CREATE TABLE IF NOT EXISTS tblMessage(\
\r
145 MessageID INTEGER PRIMARY KEY,\
\r
146 IdentityID INTEGER,\
\r
151 MessageUUID TEXT UNIQUE,\
\r
152 ReplyBoardID INTEGER,\
\r
156 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageReplyTo(\
\r
157 MessageID INTEGER,\
\r
158 ReplyToMessageUUID INTEGER,\
\r
159 ReplyOrder INTEGER\
\r
162 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageBoard(\
\r
163 MessageID INTEGER,\
\r
167 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListRequests(\
\r
168 IdentityID INTEGER,\
\r
170 RequestIndex INTEGER,\
\r
171 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
174 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageRequests(\
\r
175 IdentityID INTEGER,\
\r
177 RequestIndex INTEGER,\
\r
178 FromMessageList BOOL CHECK(FromMessageList IN('true','false')) DEFAULT 'false',\
\r
179 Found BOOL CHECK(Found IN('true','false')) DEFAULT 'false'\
\r
182 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageInserts(\
\r
183 LocalIdentityID INTEGER,\
\r
185 InsertIndex INTEGER,\
\r
186 MessageUUID TEXT UNIQUE,\
\r
188 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
191 db->Execute("CREATE TABLE IF NOT EXISTS tblMessageListInserts(\
\r
192 LocalIdentityID INTEGER,\
\r
194 InsertIndex INTEGER,\
\r
195 Inserted BOOL CHECK(Inserted IN('true','false')) DEFAULT 'false'\
\r
198 // low / high / message count for each board
\r
199 db->Execute("CREATE VIEW IF NOT EXISTS vwBoardStats AS \
\r
200 SELECT tblBoard.BoardID AS 'BoardID', IFNULL(MIN(MessageID),0) AS 'LowMessageID', IFNULL(MAX(MessageID),0) AS 'HighMessageID', COUNT(MessageID) AS 'MessageCount' \
\r
201 FROM tblBoard LEFT JOIN tblMessageBoard ON tblBoard.BoardID=tblMessageBoard.BoardID \
\r
202 WHERE MessageID>=0 \
\r
203 GROUP BY tblBoard.BoardID;");
\r
205 // calculates peer trust
\r
206 db->Execute("CREATE VIEW IF NOT EXISTS vwCalculatedPeerTrust AS \
\r
207 SELECT TargetIdentityID, \
\r
208 ROUND(SUM(MessageTrust*(LocalMessageTrust/100.0))/SUM(LocalMessageTrust/100.0),0) AS 'PeerMessageTrust', \
\r
209 ROUND(SUM(TrustListTrust*(LocalTrustListTrust/100.0))/SUM(LocalTrustListTrust/100.0),0) AS 'PeerTrustListTrust' \
\r
210 FROM tblPeerTrust INNER JOIN tblIdentity ON tblPeerTrust.IdentityID=tblIdentity.IdentityID \
\r
211 WHERE LocalTrustListTrust>=(SELECT OptionValue FROM tblOption WHERE Option='MinLocalTrustListTrust') \
\r
212 GROUP BY TargetIdentityID;");
\r
214 // update PeerTrustLevel when deleting a record from tblPeerTrust
\r
215 db->Execute("CREATE TRIGGER trgDeleteOntblPeerTrust AFTER DELETE ON tblPeerTrust \
\r
218 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
221 // update PeerTrustLevel when inserting a record into tblPeerTrust
\r
222 db->Execute("CREATE TRIGGER trgInsertOntblPeerTrust AFTER INSERT ON tblPeerTrust \
\r
225 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
228 // update PeerTrustLevel when updating a record in tblPeerTrust
\r
229 db->Execute("CREATE TRIGGER trgUpdateOntblPeerTrust AFTER UPDATE ON tblPeerTrust \
\r
232 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
233 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
236 // 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
237 db->Execute("CREATE TRIGGER trgUpdateLocalTrustLevels AFTER UPDATE OF LocalMessageTrust,LocalTrustListTrust ON tblIdentity \
\r
240 UPDATE tblIdentity SET PeerMessageTrust=(SELECT PeerMessageTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID), PeerTrustListTrust=(SELECT PeerTrustListTrust FROM vwCalculatedPeerTrust WHERE TargetIdentityID=IdentityID);\
\r
243 // delete introduction puzzles that were half-way inserted
\r
244 db->Execute("DELETE FROM tblIntroductionPuzzleInserts WHERE Day IS NULL AND InsertIndex IS NULL;");
\r
248 void SetupDefaultOptions()
\r
250 // 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
252 std::ostringstream tempstr; // must set tempstr to "" between db inserts
\r
253 SQLite3DB::DB *db=SQLite3DB::DB::instance();
\r
254 SQLite3DB::Statement st=db->Prepare("INSERT INTO tblOption(Option,OptionValue,OptionDescription) VALUES(?,?,?);");
\r
258 tempstr << LogFile::LOGLEVEL_DEBUG;
\r
259 st.Bind(0,"LogLevel");
\r
260 st.Bind(1,tempstr.str());
\r
261 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
266 st.Bind(0,"NNTPListenPort");
\r
268 st.Bind(2,"The port that the NNTP service will listen for incoming connections.");
\r
272 // NNTPBindAddresses
\r
273 st.Bind(0,"NNTPBindAddresses");
\r
274 st.Bind(1,"localhost");
\r
275 st.Bind(2,"A comma separated list of valid IPv4 or IPv6 addresses/hostnames that the NNTP service will try to bind to.");
\r
279 st.Bind(0,"NNTPAllowPost");
\r
281 st.Bind(2,"Allow posting messages from NNTP. Setting to false will make the newsgroups read only.");
\r
286 st.Bind(0,"StartNNTP");
\r
288 st.Bind(2,"Start NNTP service.");
\r
292 // StartFreenetUpdater
\r
293 st.Bind(0,"StartFreenetUpdater");
\r
295 st.Bind(2,"Start Freenet Updater thread.");
\r
300 st.Bind(0,"FCPHost");
\r
301 st.Bind(1,"localhost");
\r
302 st.Bind(2,"Host name or address of Freenet node.");
\r
307 st.Bind(0,"FCPPort");
\r
309 st.Bind(2,"The port that Freenet is listening for FCP connections on.");
\r
313 st.Bind(0,"MessageBase");
\r
315 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
319 st.Bind(0,"MaxIdentityRequests");
\r
321 st.Bind(2,"Maximum number of concurrent requests for new Identity xml files");
\r
325 st.Bind(0,"MaxIdentityIntroductionRequests");
\r
327 st.Bind(2,"Maximum number of concurrent identities requesting IdentityIntroduction xml files. Each identity may have multiple requests pending.");
\r
331 st.Bind(0,"MaxIntroductionPuzzleRequests");
\r
333 st.Bind(2,"Maximum number of concurrent requests for new IntroductionPuzzle xml files");
\r
337 st.Bind(0,"MaxTrustListRequests");
\r
339 st.Bind(2,"Maximum number of concurrent requests for new Trust Lists");
\r
343 st.Bind(0,"MaxMessageListRequests");
\r
345 st.Bind(2,"Maximum number of concurrent requests for new Message Lists");
\r
349 st.Bind(0,"MaxMessageRequests");
\r
351 st.Bind(2,"Maximum number of concurrent requests for new Messages");
\r
355 st.Bind(0,"MinLocalMessageTrust");
\r
357 st.Bind(2,"Specifies a local message trust level that a peer must have before its messages will be downloaded.");
\r
361 st.Bind(0,"MinLocalTrustListTrust");
\r
363 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
367 st.Bind(0,"MessageDownloadMaxDaysBackward");
\r
369 st.Bind(2,"The maximum number of days backward that messages will be downloaded from each identity");
\r
373 st.Bind(0,"MessageListDaysBackward");
\r
375 st.Bind(2,"The number of days backward that messages you have inserted will appear in your MessageLists");
\r
381 void SetupLogFile()
\r
384 std::string configval;
\r
387 date.SetToGMTime();
\r
389 LogFile::instance()->SetFileName("fms-"+date.Format("%Y-%m-%d")+".log");
\r
390 LogFile::instance()->OpenFile();
\r
391 LogFile::instance()->SetWriteNewLine(true);
\r
392 LogFile::instance()->SetWriteDate(true);
\r
393 LogFile::instance()->SetWriteLogLevel(true);
\r
395 if(Option::instance()->Get("LogLevel",configval)==false)
\r
398 Option::instance()->Set("LogLevel",configval);
\r
400 if(StringFunctions::Convert(configval,loglevel)==false)
\r
402 loglevel=LogFile::LOGLEVEL_DEBUG;
\r
403 Option::instance()->Set("LogLevel",loglevel);
\r
405 LogFile::instance()->SetLogLevel((LogFile::LogLevel)loglevel);
\r
408 void SetupNetwork()
\r
412 WSAStartup(MAKEWORD(2,2),&wsadata);
\r
416 void ShutdownNetwork()
\r
423 void ShutdownThreads(std::vector<ZThread::Thread *> &threads)
\r
425 std::vector<ZThread::Thread *>::iterator i;
\r
426 for(i=threads.begin(); i!=threads.end(); i++)
\r
428 if((*i)->wait(1)==false)
\r
440 for(i=threads.begin(); i!=threads.end(); i++)
\r
450 void StartThreads(std::vector<ZThread::Thread *> &threads)
\r
452 std::string startfreenet;
\r
453 std::string startnntp;
\r
455 if(Option::instance()->Get("StartFreenetUpdater",startfreenet)==false)
\r
457 startfreenet="true";
\r
458 Option::instance()->Set("StartFreenetUpdater","true");
\r
461 if(Option::instance()->Get("StartNNTP",startnntp)==false)
\r
464 Option::instance()->Set("StartNNTP","true");
\r
467 if(startfreenet=="true")
\r
469 ZThread::Thread *t=new ZThread::Thread(new FreenetMasterThread());
\r
470 threads.push_back(t);
\r
473 if(startnntp=="true")
\r
475 ZThread::Thread *t=new ZThread::Thread(new NNTPListener());
\r
476 threads.push_back(t);
\r