Branch data Line data Source code
1 : : // $Id: Serializer.h 6752 2009-06-14 04:24:52Z vern $
2 : :
3 : : #ifndef SERIALIZER_H
4 : : #define SERIALIZER_H
5 : :
6 : : #include <map>
7 : : #include <list>
8 : : #include <pcap.h>
9 : :
10 : : #include "ID.h"
11 : : #include "List.h"
12 : : #include "Expr.h"
13 : : #include "ChunkedIO.h"
14 : : #include "SerializationFormat.h"
15 : : #include "StateAccess.h"
16 : : #include "PriorityQueue.h"
17 : : #include "SerialInfo.h"
18 : : #include "IP.h"
19 : : #include "Timer.h"
20 : : #include "IOSource.h"
21 : :
22 : : class SerializationCache;
23 : : class SerialInfo;
24 : :
25 : : class Connection;
26 : : class Timer;
27 : : class Packet;
28 : :
29 : : class Serializer {
30 : : public:
31 : : // Currently ID serialization is the only method which may suspend.
32 : : bool Serialize(SerialInfo* info, const ID& id);
33 : : bool Serialize(SerialInfo* info, const char* func, val_list* args);
34 : : bool Serialize(SerialInfo* info, const StateAccess& s);
35 : : bool Serialize(SerialInfo* info, const Connection& c);
36 : : bool Serialize(SerialInfo* info, const Timer& t);
37 : : bool Serialize(SerialInfo* info, const Packet& p);
38 : :
39 : : // Access to the current cache.
40 : 172 : SerializationCache* Cache() { return current_cache; }
41 : 3 : void SetCache(SerializationCache* cache)
42 : 3 : { current_cache = cache; }
43 : :
44 : : // Input/output methods.
45 : :
46 : : #define DECLARE_READ(type) \
47 : : bool Read(type* v, const char* tag) { return format->Read(v, tag); }
48 : :
49 : : #define DECLARE_WRITE(type) \
50 : : bool Write(type v, const char* tag) \
51 : : { return format->Write(v, tag); }
52 : :
53 : : #define DECLARE_IO(type) \
54 : : DECLARE_READ(type) \
55 : : DECLARE_WRITE(type)
56 : :
57 : 155 : DECLARE_IO(int)
58 : 65 : DECLARE_IO(uint16)
59 : 0 : DECLARE_IO(uint32)
60 : 0 : DECLARE_IO(int64)
61 : 110 : DECLARE_IO(uint64)
62 : 48 : DECLARE_IO(char)
63 : 294 : DECLARE_IO(bool)
64 : 4 : DECLARE_IO(double)
65 : :
66 : 0 : bool Read(char** str, int* len, const char* tag)
67 : 0 : { return format->Read(str, len, tag); }
68 : 0 : bool Read(const char** str, int* len, const char* tag)
69 : : // This cast is ok.
70 : 0 : { return format->Read(const_cast<char**>(str), len, tag); }
71 : :
72 : : bool Read(string* s, const char* tag);
73 : :
74 : 42 : bool Write(const char* s, const char* tag)
75 : 42 : { return format->Write(s, tag); }
76 : 0 : bool Write(const char* buf, int len, const char* tag)
77 : 0 : { return format->Write(buf, len, tag); }
78 : 0 : bool Write(const string& s, const char* tag)
79 : 0 : { return format->Write(s.data(), s.size(), tag); }
80 : :
81 : 85 : bool WriteOpenTag(const char* tag)
82 : 85 : { return format->WriteOpenTag(tag); }
83 : 84 : bool WriteCloseTag(const char* tag)
84 : 84 : { return format->WriteCloseTag(tag); }
85 : :
86 : 1 : bool WriteSeparator() { return format->WriteSeparator(); }
87 : :
88 : : void Error(const char* msg);
89 : : void Warning(const char* msg);
90 : :
91 : 2 : void SetErrorDescr(const char* descr)
92 [ + + ]: 2 : { delete [] error_descr; error_descr = copy_string(descr); }
93 : :
94 : : protected:
95 : : // Format defaults to binary serialization.
96 : : Serializer(SerializationFormat* format = 0);
97 : : virtual ~Serializer();
98 : :
99 : : // Reads next object.
100 : : // If 'block' is true, wait until an object can be read.
101 : : // Returns 0 if no more object available, -1 on error.
102 : : int Unserialize(UnserialInfo* info, bool block = false);
103 : :
104 : : // Callback for error messages.
105 : : virtual void ReportError(const char* msg) = 0;
106 : :
107 : : // Callbacks for unserialized objects.
108 : :
109 : : // id points to ID in global scope, val is unserialized value.
110 : : virtual void GotID(ID* id, Val* val) = 0;
111 : : virtual void GotEvent(const char* name, double time,
112 : : EventHandlerPtr event, val_list* args) = 0;
113 : : virtual void GotFunctionCall(const char* name, double time,
114 : : Func* func, val_list* args) = 0;
115 : : virtual void GotStateAccess(StateAccess* s) = 0;
116 : : virtual void GotTimer(Timer* t) = 0;
117 : : virtual void GotConnection(Connection* c) = 0;
118 : : virtual void GotPacket(Packet* packet) = 0;
119 : :
120 : : // Magic to recognize state files.
121 : : static const uint32 MAGIC = 0x42525354;
122 : :
123 : : // This will be increased whenever there is an incompatible change
124 : : // in the data format.
125 : : static const uint32 DATA_FORMAT_VERSION = 18;
126 : :
127 : : ChunkedIO* io;
128 : :
129 : : private:
130 : : bool StartSerialization(SerialInfo* info, const char* descr, char tag);
131 : : bool EndSerialization(SerialInfo* info);
132 : :
133 : : bool UnserializeID(UnserialInfo* info);
134 : : bool UnserializeCall(UnserialInfo* info);
135 : : bool UnserializeStateAccess(UnserialInfo* info);
136 : : bool UnserializeTimer(UnserialInfo* info);
137 : : bool UnserializeConnection(UnserialInfo* info);
138 : : bool UnserializePacket(UnserialInfo* info);
139 : :
140 : : SerializationFormat* format;
141 : : SerializationCache* current_cache;
142 : : const char* error_descr; // used in error messages
143 : : };
144 : :
145 : :
146 : :
147 : : // We maintain an LRU-cache for some of the objects which have already been
148 : : // serialized. For the cache, we need two types of IDs: TransientIDs (defined
149 : : // in SerialObj.cc) uniquely reference an object during the lifetime of a
150 : : // process. PermanentIDs uniquely reference an object within a serialization.
151 : :
152 : : class SerializationCache {
153 : : public:
154 : : typedef uint64 PermanentID;
155 : : static const PermanentID NONE = 0;
156 : :
157 : : // If max_cache_size is greater than zero, we'll remove old entries
158 : : // automatically if limit is reached (LRU expiration).
159 : : SerializationCache(unsigned int max_cache_size = 0);
160 : : ~SerializationCache();
161 : :
162 : : PermanentID Register(const SerialObj* obj, PermanentID pid,
163 : : bool new_cache_strategy);
164 : :
165 : 0 : const SerialObj* Lookup(PermanentID pid)
166 : : {
167 : 0 : PIDMap::const_iterator i = pid_map.find(pid);
168 [ # # ]: 0 : if ( i == pid_map.end() )
169 : 0 : return 0;
170 : :
171 [ # # ]: 0 : assert(i->second);
172 : 0 : MoveEntryToTail(i->second);
173 : 0 : return i->second->obj.serial;
174 : : }
175 : :
176 : 107 : PermanentID Lookup(const TransientID& tid)
177 : : {
178 : 107 : TIDMap::const_iterator i = tid_map.find(tid.Value());
179 [ + + ]: 107 : if ( i == tid_map.end() )
180 : 65 : return 0;
181 : :
182 : 42 : uint64 modified = i->second->obj.serial->LastModified();
183 [ + - - + ]: 42 : if ( modified == SerialObj::ALWAYS || modified > i->second->time )
[ - + ]
184 : 0 : return 0;
185 : :
186 [ - + ]: 42 : assert(i->second);
187 : 42 : MoveEntryToTail(i->second);
188 : 107 : return i->second->pid;
189 : : }
190 : :
191 : 0 : unsigned int GetMaxCacheSize() const { return max_cache_size; }
192 : 0 : void SetMaxCacheSize(unsigned int size) { max_cache_size = size; }
193 : :
194 : : // These methods have to be called at the start/end of the
195 : : // serialization of an entity. The cache guarentees that objects
196 : : // registered after Begin() remain valid until End() is called.
197 : : // After End(), objects which are not derived from BroObj are
198 : : // discarded; others *may* remain valid.
199 : 2 : void Begin(bool can_keep_in_cache) { End(can_keep_in_cache); }
200 : : void End(bool can_keep_in_cache);
201 : :
202 : : void Clear();
203 : :
204 : : private:
205 : :
206 : : struct CacheList;
207 : :
208 : : struct CacheEntry {
209 : : union {
210 : : const SerialObj* serial;
211 : : const BroObj* bro;
212 : : } obj;
213 : :
214 : : bool is_bro_obj;
215 : : PermanentID pid;
216 : : TransientID::ID tid;
217 : : uint64 time;
218 : : struct CacheList* cache;
219 : : CacheEntry* prev;
220 : : CacheEntry* next;
221 : :
222 : : SerialType stype; // primarily for debugging
223 : : };
224 : :
225 : : // We maintain two LRU-sorted lists, one for often-changing objects and
226 : : // one for only rarely changing objects;
227 : : struct CacheList {
228 : : CacheEntry* head;
229 : : CacheEntry* tail;
230 : : unsigned int size;
231 : : };
232 : :
233 : : void RemoveEntry(CacheEntry* e);
234 : : void UnlinkEntry(CacheEntry* e);
235 : : void MoveEntryToTail(CacheEntry* e);
236 : :
237 : : unsigned int max_cache_size;
238 : :
239 : : typedef map<PermanentID, CacheEntry*> PIDMap;
240 : : typedef map<TransientID::ID, CacheEntry*> TIDMap;
241 : :
242 : : TIDMap tid_map;
243 : : PIDMap pid_map;
244 : :
245 : : CacheList cache_stable;
246 : : CacheList cache_unstable;
247 : :
248 : : // Objects in the cache which aren't derived from BroObj. These are
249 : : // always stored in the unstable cache.
250 : : typedef list<CacheEntry*> VolatileList;
251 : : VolatileList volatiles;
252 : :
253 : : PermanentID next_id;
254 : : };
255 : :
256 : : // A serializer for cloning objects. Objects can be serialized into
257 : : // the serializer and unserialized into new objects. An absolutely
258 : : // minimal implementation of Serializer!
259 : : class CloneSerializer : public Serializer {
260 : : public:
261 : 0 : CloneSerializer(SerializationFormat* format = 0) : Serializer(format) { }
262 [ # # ][ # # ]: 0 : virtual ~CloneSerializer() { }
263 : :
264 : : protected:
265 : 0 : virtual void ReportError(const char* msg) { run_time(msg); }
266 : 0 : virtual void GotID(ID* id, Val* val) { }
267 : : virtual void GotEvent(const char* name, double time,
268 : 0 : EventHandlerPtr event, val_list* args) { }
269 : : virtual void GotFunctionCall(const char* name, double time,
270 : 0 : Func* func, val_list* args) { }
271 [ # # ]: 0 : virtual void GotStateAccess(StateAccess* s) { delete s; }
272 : 0 : virtual void GotTimer(Timer* t) { }
273 : 0 : virtual void GotConnection(Connection* c) { }
274 : 0 : virtual void GotPacket(Packet* packet) { }
275 : : };
276 : :
277 : : // Write values/events to file or fd.
278 : : class FileSerializer : public Serializer {
279 : : public:
280 : : FileSerializer(SerializationFormat* format = 0);
281 : : virtual ~FileSerializer();
282 : :
283 : : // Opens the file for serialization.
284 : : bool Open(const char* file, bool pure = false);
285 : : bool Close();
286 : :
287 : : // Reads the file.
288 : : bool Read(UnserialInfo* info, const char* file, bool header = true);
289 : :
290 : : protected:
291 : : virtual void ReportError(const char* msg);
292 : : virtual void GotID(ID* id, Val* val);
293 : : virtual void GotEvent(const char* name, double time,
294 : : EventHandlerPtr event, val_list* args);
295 : : virtual void GotFunctionCall(const char* name, double time,
296 : : Func* func, val_list* args);
297 : : virtual void GotStateAccess(StateAccess* s);
298 : : virtual void GotTimer(Timer* t);
299 : : virtual void GotConnection(Connection* c);
300 : : virtual void GotPacket(Packet* packet);
301 : :
302 : : bool OpenFile(const char* file, bool readonly, bool should_exist = false);
303 : : void CloseFile();
304 : : bool ReadFile(const char* file);
305 : : bool PrepareForWriting();
306 : : bool ReadHeader(UnserialInfo* info = 0);
307 : :
308 : : SerializationCache cache;
309 : : const char* file;
310 : : int fd;
311 : : };
312 : :
313 : : // Converts from one serialization format into another.
314 : : class ConversionSerializer:public FileSerializer {
315 : : public:
316 : : ConversionSerializer(SerializationFormat* in, SerializationFormat* out);
317 : : virtual ~ConversionSerializer();
318 : :
319 : : bool Convert(const char* file_in, const char* file_out);
320 : :
321 : : protected:
322 : : virtual void GotID(ID* id, Val* val);
323 : : virtual void GotEvent(const char* name, double time,
324 : : EventHandlerPtr event, val_list* args);
325 : : virtual void GotFunctionCall(const char* name, double time,
326 : : Func* func, val_list* args);
327 : : virtual void GotStateAccess(StateAccess* s);
328 : : virtual void GotPacket(Packet* packet);
329 : :
330 : : FileSerializer* serout;
331 : : };
332 : :
333 : :
334 : : // Abstract interface class for external sources providing a stream of events.
335 : : class EventSource {
336 : : public:
337 : : virtual ~EventSource() { }
338 : :
339 : : // Returns time of the oldest event (0 if none available).
340 : : virtual double NextTimestamp(double* local_network_time) = 0;
341 : :
342 : : // Dispatches the oldest event and removes it.
343 : : virtual void DispatchNextEvent() = 0;
344 : :
345 : : // Returns true if there are more events to expect from this source.
346 : : virtual bool IsActive() = 0;
347 : : };
348 : :
349 : : // Plays a file of events back.
350 : : class EventPlayer : public FileSerializer, public IOSource {
351 : : public:
352 : : EventPlayer(const char* file);
353 : : virtual ~EventPlayer();
354 : :
355 : : virtual void GetFds(int* read, int* write, int* except);
356 : : virtual double NextTimestamp(double* local_network_time);
357 : : virtual void Process();
358 : 0 : virtual const char* Tag() { return "EventPlayer"; }
359 : :
360 : : protected:
361 : 0 : virtual void GotID(ID* id, Val* val) {}
362 : : virtual void GotEvent(const char* name, double time,
363 : : EventHandlerPtr event, val_list* args);
364 : : virtual void GotFunctionCall(const char* name, double time,
365 : : Func* func, val_list* args);
366 : :
367 : : double stream_time; // time of first captured event
368 : : double replay_time; // network time of replay start
369 : :
370 : : // Next event waiting to be dispatched.
371 : : double ne_time;
372 : : EventHandlerPtr ne_handler;
373 : : val_list* ne_args;
374 : :
375 : : };
376 : :
377 : :
378 : : // A link-layer packet.
379 : : //
380 : : // Eventually we should use something like this consistently throughout Bro,
381 : : // replacing the current packet arguments in functions like *::NextPacket().
382 : : // Before doing this, though, we should consider provisioning for packet
383 : : // formats other than just libpcap by designing a more abstract interface.
384 : : //
385 : : // Note that for serialization we don't use much of the support provided by
386 : : // the serialization framework. Serialize/Unserialize do all the work by
387 : : // themselves. In particular, Packets aren't derived from SerialObj. They are
388 : : // completely seperate and self-contained entities, and we don't need any of
389 : : // the sophisticated features like object caching.
390 : :
391 : : class Packet {
392 : : public:
393 : : // Argument is whether we should delete associatd memory upon
394 : : // destruction.
395 : 0 : Packet(TimerMgr::Tag arg_tag, bool arg_free = false)
396 : 0 : {
397 : 0 : time = 0.0;
398 : 0 : hdr = 0;
399 : 0 : pkt = 0;
400 : 0 : hdr_size = 0;
401 : 0 : free = arg_free;
402 : 0 : tag = arg_tag;
403 : 0 : }
404 : :
405 : 0 : ~Packet()
406 : : {
407 [ # # ]: 0 : if ( free )
408 : : {
409 : 0 : delete hdr;
410 [ # # ]: 0 : delete [] pkt;
411 : : }
412 : 0 : }
413 : :
414 : 0 : const IP_Hdr IP() const
415 : 0 : { return IP_Hdr((struct ip *) (pkt + hdr_size)); }
416 : :
417 : : void Describe(ODesc* d) const;
418 : :
419 : : bool Serialize(SerialInfo* info) const;
420 : : static Packet* Unserialize(UnserialInfo* info);
421 : :
422 : : const struct pcap_pkthdr* hdr;
423 : : const u_char* pkt;
424 : : TimerMgr::Tag tag;
425 : : uint32 link_type;
426 : :
427 : : double time;
428 : : int hdr_size;
429 : :
430 : : private:
431 : : bool free;
432 : : };
433 : :
434 : : extern FileSerializer* event_serializer;
435 : : extern FileSerializer* state_serializer;
436 : :
437 : : #endif
|