version 0.3.29
[fms.git] / src / freenet / identityintroductioninserter.cpp
1 #include "../../include/freenet/identityintroductioninserter.h"\r
2 #include "../../include/freenet/identityintroductionxml.h"\r
3 #include "../../include/stringfunctions.h"\r
4 #include "../../include/hex.h"\r
5 #include "../../include/option.h"\r
6 \r
7 #include <Poco/SHA1Engine.h>\r
8 \r
9 #ifdef XMEM\r
10         #include <xmem.h>\r
11 #endif\r
12 \r
13 IdentityIntroductionInserter::IdentityIntroductionInserter(SQLite3DB::DB *db):IDatabase(db)\r
14 {\r
15         Initialize();\r
16 }\r
17 \r
18 IdentityIntroductionInserter::IdentityIntroductionInserter(SQLite3DB::DB *db, FCPv2::Connection *fcp):IDatabase(db),IFCPConnected(fcp)\r
19 {\r
20         Initialize();\r
21 }\r
22 \r
23 void IdentityIntroductionInserter::CheckForNewInserts()\r
24 {\r
25         SQLite3DB::Recordset rs=m_db->Query("SELECT LocalIdentityID, Day, UUID, Solution FROM tblIdentityIntroductionInserts WHERE Inserted='false';");\r
26         if(!rs.Empty())\r
27         {\r
28                 if(rs.GetField(0) && rs.GetField(1) && rs.GetField(2))\r
29                 {\r
30                         StartInsert(rs.GetInt(0),rs.GetField(1),rs.GetField(2),rs.GetField(3));\r
31                 }\r
32         }\r
33 }\r
34 \r
35 void IdentityIntroductionInserter::FCPConnected()\r
36 {\r
37         m_inserting=false;\r
38 }\r
39 \r
40 void IdentityIntroductionInserter::FCPDisconnected()\r
41 {\r
42 \r
43 }\r
44 \r
45 const bool IdentityIntroductionInserter::HandleMessage(FCPv2::Message &message)\r
46 {\r
47 \r
48         if(message["Identifier"].find("IdentityIntroductionInserter")==0)\r
49         {\r
50                 std::vector<std::string> idparts;\r
51                 StringFunctions::Split(message["Identifier"],"|",idparts);\r
52                 \r
53                 // no action for URIGenerated\r
54                 if(message.GetName()=="URIGenerated")\r
55                 {\r
56                         return true;\r
57                 }\r
58 \r
59                 if(message.GetName()=="PutFailed")\r
60                 {\r
61                         // if fatal error, or data is already there - remove insert from database\r
62                         if(message["Fatal"]=="true" || message["Code"]=="9")\r
63                         {\r
64                                 m_db->Execute("DELETE FROM tblIdentityIntroductionInserts WHERE UUID='"+idparts[3]+"';");\r
65                                 // update the puzzle from the request table (set to not found) because we don't need it anymore and don't want to user tyring to solve it again\r
66                                 m_db->Execute("UPDATE tblIntroductionPuzzleRequests SET Found='false' WHERE UUID='"+idparts[3]+"';");\r
67                                 m_log->warning("IdentityIntroductionInserter::HandleMessage received fatal error trying to insert IdentityIntroduction "+idparts[3]);\r
68                         }\r
69                         m_inserting=false;\r
70                         return true;\r
71                 }\r
72 \r
73                 if(message.GetName()=="PutSuccessful")\r
74                 {\r
75                         m_db->Execute("UPDATE tblIdentityIntroductionInserts SET Inserted='true' WHERE UUID='"+idparts[3]+"';");\r
76                         m_inserting=false;\r
77                         m_log->information("IdentityIntroductionInserter::HandleMessage successfully inserted IdentityIntroduction "+idparts[3]);\r
78                         return true;\r
79                 }\r
80 \r
81                 if(message.GetName()=="IdentifierCollision")\r
82                 {\r
83                         m_inserting=false;\r
84                         return true;\r
85                 }\r
86         }\r
87 \r
88         return false;\r
89 }\r
90 \r
91 void IdentityIntroductionInserter::Initialize()\r
92 {\r
93         m_inserting=false;\r
94         Option option(m_db);\r
95         option.Get("MessageBase",m_messagebase);\r
96 }\r
97 \r
98 void IdentityIntroductionInserter::Process()\r
99 {\r
100         Poco::DateTime now;\r
101 \r
102         // only do 1 insert at a time\r
103         if(!m_inserting && m_lastchecked<(now-Poco::Timespan(0,0,1,0,0)))\r
104         {\r
105                 CheckForNewInserts();\r
106                 m_lastchecked=now;\r
107         }\r
108 }\r
109 \r
110 void IdentityIntroductionInserter::RegisterWithThread(FreenetMasterThread *thread)\r
111 {\r
112         thread->RegisterFCPConnected(this);\r
113         thread->RegisterFCPMessageHandler(this);\r
114         thread->RegisterPeriodicProcessor(this);\r
115 }\r
116 \r
117 void IdentityIntroductionInserter::StartInsert(const long localidentityid, const std::string &day, const std::string &UUID, const std::string &solution)\r
118 {\r
119         FCPv2::Message message;\r
120         IdentityIntroductionXML xml;\r
121         std::string publickey;\r
122         std::string data;\r
123         std::string datasizestr;\r
124         std::string encodedhash;\r
125         \r
126         SQLite3DB::Statement st=m_db->Prepare("SELECT PublicKey FROM tblLocalIdentity WHERE PublicKey IS NOT NULL AND PublicKey<>'' AND LocalIdentityID=?;");\r
127         st.Bind(0,localidentityid);\r
128         st.Step();\r
129 \r
130         if(st.RowReturned())\r
131         {\r
132                 st.ResultText(0,publickey);\r
133 \r
134                 xml.SetIdentity(publickey);\r
135                 data=xml.GetXML();\r
136                 StringFunctions::Convert(data.size(),datasizestr);\r
137 \r
138                 Poco::SHA1Engine sha1;\r
139                 sha1.update(solution);\r
140                 encodedhash=Poco::DigestEngine::digestToHex(sha1.digest());\r
141                 StringFunctions::UpperCase(encodedhash,encodedhash);\r
142 \r
143                 message.SetName("ClientPut");\r
144                 message["URI"]="KSK@"+m_messagebase+"|"+day+"|"+UUID+"|"+encodedhash+".xml";\r
145                 message["Identifier"]="IdentityIntroductionInserter|"+message["URI"];\r
146                 message["UploadFrom"]="direct";\r
147                 message["DataLength"]=datasizestr;\r
148 \r
149                 m_fcp->Send(message);\r
150                 m_fcp->Send(std::vector<char>(data.begin(),data.end()));\r
151 \r
152                 m_inserting=true;\r
153         }\r
154         else\r
155         {\r
156                 m_log->debug("IdentityIntroductionInserter::StartInsert could not find a public key for identity.  It is probably a new identity that doesn't have a key yet.");\r
157         }\r
158 \r
159 }\r