|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #ifndef HashStore_h__ |
|
6 #define HashStore_h__ |
|
7 |
|
8 #include "Entries.h" |
|
9 #include "ChunkSet.h" |
|
10 |
|
11 #include "nsString.h" |
|
12 #include "nsTArray.h" |
|
13 #include "nsIFile.h" |
|
14 #include "nsIFileStreams.h" |
|
15 #include "nsCOMPtr.h" |
|
16 |
|
17 namespace mozilla { |
|
18 namespace safebrowsing { |
|
19 |
|
20 // A table update is built from a single update chunk from the server. As the |
|
21 // protocol parser processes each chunk, it constructs a table update with the |
|
22 // new hashes. |
|
23 class TableUpdate { |
|
24 public: |
|
25 TableUpdate(const nsACString& aTable) |
|
26 : mTable(aTable), mLocalUpdate(false) {} |
|
27 const nsCString& TableName() const { return mTable; } |
|
28 |
|
29 bool Empty() const { |
|
30 return mAddChunks.Length() == 0 && |
|
31 mSubChunks.Length() == 0 && |
|
32 mAddExpirations.Length() == 0 && |
|
33 mSubExpirations.Length() == 0 && |
|
34 mAddPrefixes.Length() == 0 && |
|
35 mSubPrefixes.Length() == 0 && |
|
36 mAddCompletes.Length() == 0 && |
|
37 mSubCompletes.Length() == 0; |
|
38 } |
|
39 |
|
40 // Throughout, uint32_t aChunk refers only to the chunk number. Chunk data is |
|
41 // stored in the Prefix structures. |
|
42 void NewAddChunk(uint32_t aChunk) { mAddChunks.Set(aChunk); } |
|
43 void NewSubChunk(uint32_t aChunk) { mSubChunks.Set(aChunk); } |
|
44 |
|
45 void NewAddExpiration(uint32_t aChunk) { mAddExpirations.Set(aChunk); } |
|
46 void NewSubExpiration(uint32_t aChunk) { mSubExpirations.Set(aChunk); } |
|
47 |
|
48 void NewAddPrefix(uint32_t aAddChunk, const Prefix& aPrefix); |
|
49 void NewSubPrefix(uint32_t aAddChunk, const Prefix& aPrefix, uint32_t aSubChunk); |
|
50 |
|
51 void NewAddComplete(uint32_t aChunk, const Completion& aCompletion); |
|
52 void NewSubComplete(uint32_t aAddChunk, const Completion& aCompletion, |
|
53 uint32_t aSubChunk); |
|
54 void SetLocalUpdate(void) { mLocalUpdate = true; } |
|
55 bool IsLocalUpdate(void) { return mLocalUpdate; } |
|
56 |
|
57 ChunkSet& AddChunks() { return mAddChunks; } |
|
58 ChunkSet& SubChunks() { return mSubChunks; } |
|
59 |
|
60 // Expirations for chunks. |
|
61 ChunkSet& AddExpirations() { return mAddExpirations; } |
|
62 ChunkSet& SubExpirations() { return mSubExpirations; } |
|
63 |
|
64 // Hashes associated with this chunk. |
|
65 AddPrefixArray& AddPrefixes() { return mAddPrefixes; } |
|
66 SubPrefixArray& SubPrefixes() { return mSubPrefixes; } |
|
67 AddCompleteArray& AddCompletes() { return mAddCompletes; } |
|
68 SubCompleteArray& SubCompletes() { return mSubCompletes; } |
|
69 |
|
70 private: |
|
71 nsCString mTable; |
|
72 // Update not from the remote server (no freshness) |
|
73 bool mLocalUpdate; |
|
74 |
|
75 // The list of chunk numbers that we have for each of the type of chunks. |
|
76 ChunkSet mAddChunks; |
|
77 ChunkSet mSubChunks; |
|
78 ChunkSet mAddExpirations; |
|
79 ChunkSet mSubExpirations; |
|
80 |
|
81 // 4-byte sha256 prefixes. |
|
82 AddPrefixArray mAddPrefixes; |
|
83 SubPrefixArray mSubPrefixes; |
|
84 |
|
85 // 32-byte hashes. |
|
86 AddCompleteArray mAddCompletes; |
|
87 SubCompleteArray mSubCompletes; |
|
88 }; |
|
89 |
|
90 // There is one hash store per table. |
|
91 class HashStore { |
|
92 public: |
|
93 HashStore(const nsACString& aTableName, nsIFile* aStoreFile); |
|
94 ~HashStore(); |
|
95 |
|
96 const nsCString& TableName() const { return mTableName; } |
|
97 |
|
98 nsresult Open(); |
|
99 // Add Prefixes are stored partly in the PrefixSet (contains the |
|
100 // Prefix data organized for fast lookup/low RAM usage) and partly in the |
|
101 // HashStore (Add Chunk numbers - only used for updates, slow retrieval). |
|
102 // AugmentAdds function joins the separate datasets into one complete |
|
103 // prefixes+chunknumbers dataset. |
|
104 nsresult AugmentAdds(const nsTArray<uint32_t>& aPrefixes); |
|
105 |
|
106 ChunkSet& AddChunks() { return mAddChunks; } |
|
107 ChunkSet& SubChunks() { return mSubChunks; } |
|
108 AddPrefixArray& AddPrefixes() { return mAddPrefixes; } |
|
109 AddCompleteArray& AddCompletes() { return mAddCompletes; } |
|
110 SubPrefixArray& SubPrefixes() { return mSubPrefixes; } |
|
111 SubCompleteArray& SubCompletes() { return mSubCompletes; } |
|
112 |
|
113 // ======= |
|
114 // Updates |
|
115 // ======= |
|
116 // Begin the update process. Reads the store into memory. |
|
117 nsresult BeginUpdate(); |
|
118 |
|
119 // Imports the data from a TableUpdate. |
|
120 nsresult ApplyUpdate(TableUpdate &aUpdate); |
|
121 |
|
122 // Process expired chunks |
|
123 nsresult Expire(); |
|
124 |
|
125 // Rebuild the store, Incorporating all the applied updates. |
|
126 nsresult Rebuild(); |
|
127 |
|
128 // Write the current state of the store to disk. |
|
129 // If you call between ApplyUpdate() and Rebuild(), you'll |
|
130 // have a mess on your hands. |
|
131 nsresult WriteFile(); |
|
132 |
|
133 // Wipe out all Completes. |
|
134 void ClearCompletes(); |
|
135 |
|
136 private: |
|
137 nsresult Reset(); |
|
138 |
|
139 nsresult ReadHeader(); |
|
140 nsresult SanityCheck(); |
|
141 nsresult CalculateChecksum(nsAutoCString& aChecksum, uint32_t aFileSize, |
|
142 bool aChecksumPresent); |
|
143 nsresult CheckChecksum(nsIFile* aStoreFile, uint32_t aFileSize); |
|
144 void UpdateHeader(); |
|
145 |
|
146 nsresult ReadChunkNumbers(); |
|
147 nsresult ReadHashes(); |
|
148 |
|
149 nsresult ReadAddPrefixes(); |
|
150 nsresult ReadSubPrefixes(); |
|
151 |
|
152 nsresult WriteAddPrefixes(nsIOutputStream* aOut); |
|
153 nsresult WriteSubPrefixes(nsIOutputStream* aOut); |
|
154 |
|
155 nsresult ProcessSubs(); |
|
156 |
|
157 // This is used for checking that the database is correct and for figuring out |
|
158 // the number of chunks, etc. to read from disk on restart. |
|
159 struct Header { |
|
160 uint32_t magic; |
|
161 uint32_t version; |
|
162 uint32_t numAddChunks; |
|
163 uint32_t numSubChunks; |
|
164 uint32_t numAddPrefixes; |
|
165 uint32_t numSubPrefixes; |
|
166 uint32_t numAddCompletes; |
|
167 uint32_t numSubCompletes; |
|
168 }; |
|
169 |
|
170 Header mHeader; |
|
171 |
|
172 // The name of the table (must end in -shavar or -digest256, or evidently |
|
173 // -simple for unittesting. |
|
174 nsCString mTableName; |
|
175 nsCOMPtr<nsIFile> mStoreDirectory; |
|
176 |
|
177 bool mInUpdate; |
|
178 |
|
179 nsCOMPtr<nsIInputStream> mInputStream; |
|
180 |
|
181 // Chunk numbers, stored as uint32_t arrays. |
|
182 ChunkSet mAddChunks; |
|
183 ChunkSet mSubChunks; |
|
184 |
|
185 ChunkSet mAddExpirations; |
|
186 ChunkSet mSubExpirations; |
|
187 |
|
188 // Chunk data for shavar tables. See Entries.h for format. |
|
189 AddPrefixArray mAddPrefixes; |
|
190 SubPrefixArray mSubPrefixes; |
|
191 |
|
192 // See bug 806422 for background. We must be able to distinguish between |
|
193 // updates from the completion server and updates from the regular server. |
|
194 AddCompleteArray mAddCompletes; |
|
195 SubCompleteArray mSubCompletes; |
|
196 }; |
|
197 |
|
198 } |
|
199 } |
|
200 #endif |