The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
frameset.c
Go to the documentation of this file.
1 
51 #include <string.h>
52 #include <projectcommon.h>
53 #include <frameset.h>
54 #include <frametypes.h>
55 #include <compressframe.h>
56 #include <generic_tlv_min.h>
57 #include <tlvhelper.h>
58 FSTATIC void _frameset_indir_finalize(void* f);
60 FSTATIC char * _frameset_toString(gconstpointer);
61 
63 
70 
72 
74 FSTATIC void
76 {
77  Frame* frame = CASTTOCLASS(Frame, f);
78  UNREF(frame);
79 }
80 
82 FSTATIC void
84 {
85  FrameSet* fs = CASTTOCLASS(FrameSet, obj);
86  g_return_if_fail(NULL != fs);
89  if (fs->framelist) {
90  // Would rather use g_slist_free_full() - but it's too new to be widely deployed...
91  while (NULL != fs->framelist) {
93  fs->framelist->data = NULL;
94  fs->framelist = g_slist_delete_link(fs->framelist, fs->framelist);
95  }
96  }
97  if (fs->packet) {
98  FREE(fs->packet);
99  fs->packet = NULL;
100  fs->pktend = NULL;
101  }
102  memset(fs, 0x0, sizeof(*fs));
103  FREECLASSOBJ(fs);
104 }
105 
106 
107 
109 FrameSet*
110 frameset_new(guint16 frameset_type)
111 {
112  AssimObj* obj = assimobj_new(sizeof(FrameSet));
113  FrameSet* s = NEWSUBCLASS(FrameSet, obj);
114 
116  g_return_val_if_fail(s != NULL, NULL);
117  s->fstype = frameset_type;
118  s->framelist = NULL;
119  s->packet = NULL;
120  s->pktend = NULL;
121  s->fsflags = 0;
125  return s;
126 }
127 
128 #define SPECIALFRAME(ftype) ((FRAMETYPE_COMPRESS == (ftype)) || (FRAMETYPE_CRYPT == (ftype)) || (FRAMETYPE_SIG == (ftype)))
129 
131 void
133  Frame* f)
134 {
135  g_return_if_fail(NULL != fs && NULL != f);
136  REF(f);
137 
138  fs->framelist = g_slist_prepend(fs->framelist, f);
139 }
140 
142 void
144  Frame* f)
145 {
146  g_return_if_fail(NULL != fs && NULL != f);
147  REF(f);
148  fs->framelist = g_slist_append(fs->framelist, f);
149 }
150 
158 void
160  SignFrame* sigframe,
161  Frame* cryptframe,
162  CompressFrame* compressframe)
164 {
167  GSList* curframe; // Current frame as we marshall packet...
168  int curpktoffset; // Current offset as we marshall packet...
169  guint8* curpktpos=NULL; // Current position within packet..
170  gsize pktsize;
171  gsize fssize = FRAMESET_INITSIZE; // "frameset" overhead size
172  g_return_if_fail(NULL != fs);
173  g_return_if_fail(NULL != sigframe);
174  // g_return_if_fail(NULL != fs->framelist); // Is an empty frame list OK?
175 
176  /*
177  * The general method we employ here is to:
178  * 1. Free the current packet, if any
179  * 2. Remove current Framelist signature, compression, and encryption frames (if any).
180  * 3. Prepend a compression Frame if compm != NULL
181  * 4. Prepend an encryption Frame if cryptm != NULL
182  * 5. Prepend a signature Frame (sigm may not be NULL).
183  * 6. Figure out how much space we think we need to malloc for the packet using Frames.
184  * 7. Malloc enough space.
185  * 8. Populate all the frames into this new packet in reverse order.
186  */
187 
188  // Free current packet, if any...
189  if (fs->packet) {
190  FREE(fs->packet);
191  fs->packet = NULL;
192  fs->pktend = NULL;
193  }
194  // Remove any current signature, compression, or encryption frames...
195  // (this method only works if they're first, and all together - but that's OK)
196  while (fs->framelist) {
197  Frame* item = CASTTOCLASS(Frame, fs->framelist->data);
198  g_return_if_fail(NULL != item);
199  switch (item->type) {
200  case FRAMETYPE_SIG:
201  case FRAMETYPE_CRYPT:
202  case FRAMETYPE_COMPRESS:
203  UNREF(item);
204  fs->framelist->data = NULL;
205  fs->framelist = g_slist_delete_link(fs->framelist, fs->framelist);
206  continue;
207  }
208  break;
209  }
230  if (NULL != compressframe) {
231  gsize estsize = FRAMESET_INITSIZE;
232  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
233  Frame* frame = CASTTOCLASS(Frame, curframe->data);
234  estsize += frame->dataspace(frame);
235  }
236  if (estsize > compressframe->compression_threshold) {
237  CompressFrame* newframe
238  = compressframe_new(compressframe->baseclass.type, compressframe->compression_method);
239  frameset_prepend_frame(fs, &newframe->baseclass);
240  UNREF2(newframe);
241  }
242  }
243  if (NULL != cryptframe) {
244  frameset_prepend_frame(fs, cryptframe);
245  }
246  // "sigframe" cannot be NULL (see check above)
247  frameset_prepend_frame(fs, CASTTOCLASS(Frame, sigframe));
248 
249  // Reverse list...
250  fs->framelist = g_slist_reverse(fs->framelist);
251 
252  // Add "end" frame to the "end" - if not already present...
253  if (CASTTOCLASS(Frame, fs->framelist->data)->type != FRAMETYPE_END) {
254  Frame* endframe = frame_new(FRAMETYPE_END, 0);
255  g_return_if_fail(NULL != endframe);
256  frameset_prepend_frame(fs, endframe);
257  UNREF(endframe);
258  }
259 
260  pktsize = fssize;
261  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
262  Frame* frame = CASTTOCLASS(Frame, curframe->data);
263  pktsize += frame->dataspace(frame);
264  }
265  fs->packet = MALLOC0(pktsize);
266  fs->pktend = ((guint8*)fs->packet + pktsize);
267  g_return_if_fail(fs->packet != NULL);
268 
269  curpktoffset = pktsize;
270 
271  // Marshall out all our data - in reverse order...
272  // WATCH OUT: compression and encryption can replace our packet(!)
273  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
274  Frame* frame = CASTTOCLASS(Frame, curframe->data);
275 
276  // frame->dataspace() may change after calling updatedata()
277  curpktoffset = curpktoffset - frame->dataspace(frame);
278  g_return_if_fail(curpktoffset >= 0);
279  curpktpos = (guint8*)fs->packet + curpktoffset;
280  set_generic_tlv_type(curpktpos, frame->type, fs->pktend);
281  set_generic_tlv_len(curpktpos, frame->length, fs->pktend);
282  frame->updatedata(frame, curpktpos, fs->pktend, fs);
283  // updatedata() can change fs->packet and fs->pktend
284  curpktpos = (guint8*)fs->packet + curpktoffset;
285  if (!frame->isvalid(frame, curpktpos, fs->pktend)) {
286  g_error("Generated %s frame is not valid(!) (length=%"G_GSIZE_FORMAT")"
287  , proj_class_classname(frame), (gsize)frame->length);
288  }
289  }
290  g_return_if_fail(curpktpos == (((guint8*)fs->packet)+fssize));
291  // Reverse list - putting it back in the right order
292  fs->framelist = g_slist_reverse(fs->framelist);
293  // Write out the initial FrameSet header.
294  set_generic_tlv_type(fs->packet, fs->fstype, ((guint8*)fs->packet)+fssize);
295  set_generic_tlv_len(fs->packet, pktsize-fssize, ((guint8*)fs->packet)+fssize);
296  tlv_set_guint16(((guint8*)fs->packet)+GENERICTLV_HDRSZ, fs->fsflags, ((guint8*)fs->packet)+fssize);
297 }
298 
300 guint16
302 {
303  g_return_val_if_fail(NULL != fs, 0xffff);
304  return fs->fsflags;
305 }
306 
308 guint16
310  guint16 flagbits)
311 {
312  g_return_val_if_fail(NULL != fs, 0xffff);
313  fs->fsflags |= flagbits;
314  return fs->fsflags;
315 }
316 
318 guint16
320  guint16 flagbits)
321 {
322  g_return_val_if_fail(NULL != fs, 0xffff);
323  g_return_val_if_fail(flagbits != 0x0000, fs->fsflags);
324  fs->fsflags &= ~flagbits;
325  return fs->fsflags;
326 }
327 
330 gpointer
332  Frame* f,
333  gpointer curpktpos)
334 {
335  guint8 * curpos = curpktpos;
336  guint8 * endpos = fs->pktend;
337 
338  g_return_val_if_fail(fs != NULL && f != NULL && fs->packet != NULL && curpktpos != NULL, NULL);
339  g_return_val_if_fail((curpos + f->dataspace(f)) <= endpos, NULL);
340 
341  tlv_set_guint16(curpos, f->type, fs->pktend);
342  curpos += 2; // sizeof(guint16)
343  tlv_set_guint24(curpos, f->length, fs->pktend);
344  curpos += 3; // 3 byte integer for length
345  if (f->length > 0) {
346  // Zero-length frames are just fine.
347  memcpy(curpos, f->value, f->length);
348  }
349  curpos += f->length;
350  return (gpointer)curpos;
351 }
352 
354 void
356 {
357  GSList* curframe;
358  g_debug("BEGIN Dumping FrameSet:");
359  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
360  Frame* frame = CASTTOCLASS(Frame, curframe->data);
361  frame->dump(frame, ".... ");
362  }
363  g_debug("END FrameSet dump");
364 }
365 
368 {
369  GSList* curframe;
370  if (self->_seqframe) {
371  return self->_seqframe;
372  }
373  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
374  Frame* frame = CASTTOCLASS(Frame, curframe->data);
375  DEBUGMSG4("%s: LOOKING AT FRAME TYPE %d (but want sequence number)", __FUNCTION__, frame->type);
376  if (frame->type == FRAMETYPE_REQID) {
377  self->_seqframe = CASTTOCLASS(SeqnoFrame, frame);
378  return self->_seqframe;
379  }
380  }
381  return NULL;
382 }
383 
384 FSTATIC char *
385 _frameset_toString(gconstpointer vself)
386 {
387  GString* gsret = NULL;
388  char* ret = NULL;
389  const FrameSet* self = CASTTOCONSTCLASS(FrameSet, vself);
390  GSList* curframe;
391  const char * comma = "";
392 
393  g_return_val_if_fail(self != NULL, NULL);
394  gsret = g_string_new("");
395  g_string_append_printf(gsret, "FrameSet(fstype=%d, [", self->fstype);
396 
397  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
398  Frame* frame = CASTTOCLASS(Frame, curframe->data);
399  char* fstr;
400  g_return_val_if_fail(frame != NULL, NULL);
401  fstr = frame->baseclass.toString(&frame->baseclass);
402  g_string_append_printf(gsret, "%s[%s]", comma, fstr);
403  comma = ", ";
404  g_free(fstr); fstr = NULL;
405  }
406  g_string_append_printf(gsret, "])");
407  ret = gsret->str;
408  g_string_free(gsret, FALSE);
409  return ret;
410 }
411 
#define MALLOC0(nbytes)
should it just call g_malloc?
Definition: projectcommon.h:25
guint16 frameset_set_flags(FrameSet *fs, guint16 flagbits)
Set (OR in) the given set of FrameSet flags.
Definition: frameset.c:309
void frameset_dump(const FrameSet *fs)
Dump out a FrameSet.
Definition: frameset.c:355
AssimObj baseclass
Definition: frameset.h:46
guint32 length
Frame Length.
Definition: frame.h:46
guint16 frameset_get_flags(FrameSet *fs)
Return the flags currently set on this FrameSet.
Definition: frameset.c:301
gpointer frame_append_to_frameset_packet(FrameSet *fs, Frame *f, gpointer curpktpos)
Append the given Frame to a FrameSet packet.
Definition: frameset.c:331
FSTATIC void _frameset_finalize(AssimObj *self)
static: finalize (free) frameset and all its constituent frames...
Definition: frameset.c:83
guint16 frameset_clear_flags(FrameSet *fs, guint16 flagbits)
Clear the given set of FrameSet flags (& ~flagbits)
Definition: frameset.c:319
#define DEBUGMSG4(...)
Definition: proj_classes.h:92
AssimObj baseclass
Base object class for our Class system.
Definition: frame.h:44
Implements minimal client-oriented Frame and Frameset capabilities.
This is the base Frame class object (in-memory TLV (type, length, value)) for every general component...
Definition: frame.h:43
SeqnoFrame *(* getseqno)(FrameSet *)
Return the sequence number for this frameset (if any)
Definition: frameset.h:54
FSTATIC char * _frameset_toString(gconstpointer)
Definition: frameset.c:385
FrameSet * frameset_new(guint16 frameset_type)
Construct a new frameset of the given type.
Definition: frameset.c:110
The SignFrame class object - implements digital signatures for FrameSets.
Definition: signframe.h:40
gpointer pktend
Last byte past the end of the packet.
Definition: frameset.h:50
#define FSTATIC
Definition: projectcommon.h:31
#define GENERICTLV_HDRSZ
Size of Generic TLV header - ((type + length) == 5)
gpointer value
Frame Value (pointer)
Definition: frame.h:47
void(* dump)(const Frame *self, const char *prefix)
member function for dumping Frame
Definition: frame.h:56
guint32 compression_threshold
Definition: compressframe.h:43
FSTATIC void _frameset_indir_finalize(void *f)
static: finalize (free) frame
Definition: frameset.c:75
#define FREECLASSOBJ(obj)
Free a C-class object.
Definition: proj_classes.h:76
guint16 fstype
Type of frameset.
Definition: frameset.h:51
void tlv_set_guint24(void *vitem, guint32 item, const void *bufend)
Set an unsigned 24 bit (3-byte) integer to the given location with error checking and without caring ...
Definition: tlvhelper.c:146
void tlv_set_guint16(void *vitem, guint16 item, const void *bufend)
Set an unsigned 16 bit integer to the given location with error checking and without caring about byt...
Definition: tlvhelper.c:68
#define BINDDEBUG(Cclass)
BINDDEBUG is for telling the class system where the debug variable for this class is - put it in the ...
Definition: proj_classes.h:82
void frameset_append_frame(FrameSet *fs, Frame *f)
Append frame to the front of the end of the frame list.
Definition: frameset.c:143
#define __FUNCTION__
CompressFrame * compressframe_new(guint16 frame_type, guint16 compression_method)
This is our CompressFrame class object - used for representing a compression method.
Definition: compressframe.h:41
Frame * frame_new(guint16 frame_type, gsize framesize)
Construct a new frame - allowing for "derived" frame types...
Definition: frame.c:124
gboolean(* isvalid)(const Frame *self, gconstpointer tlvptr, gconstpointer pktend)
TRUE if TLV data looks valid...
Definition: frame.h:50
void frameset_construct_packet(FrameSet *fs, SignFrame *sigframe, Frame *cryptframe, CompressFrame *compressframe)
Construct packet to go correspond to this frameset.
Definition: frameset.c:159
Describes interfaces to C-String Frame (Compressframe) C-Class It holds conventional zero-terminated ...
#define FREE(m)
Our interface to free.
Definition: projectcommon.h:29
#define REF(obj)
Definition: assimobj.h:39
gpointer packet
Pointer to packet (when constructed)
Definition: frameset.h:49
#define CASTTOCONSTCLASS(Cclass, obj)
Safely cast 'obj' to const C-class 'class' - verifying that it was registered as being of type class ...
Definition: proj_classes.h:71
void set_generic_tlv_type(gpointer tlv_vp, guint16 newtype, gconstpointer pktend)
Set the 'Type' of the given TLV TLV entry (first two bytes)
Project common header file.
Header file defining the data layouts for our Frames.
TLV helper interfaces definitions.
#define FRAMETYPE_CRYPT
FRAMETYPE_CRYPT Frame (frametype 2) Frame subclass - CryptFrame class.
Definition: frametypes.h:98
guint8 compression_method
Definition: compressframe.h:45
guint16 fsflags
Flags for frameset.
Definition: frameset.h:52
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
const char * proj_class_classname(gconstpointer object)
Return the class name of one of our managed objects.
Definition: proj_classes.c:324
void set_generic_tlv_len(gpointer tlv_vp, guint32 newsize, gconstpointer pktend)
Set the 'Length' of the given generic TLV entry (first 3 bytes after type)
void(* _finalize)(AssimObj *)
Free object (private)
Definition: assimobj.h:55
guint16 type
Frame Type (see Individual TLV 'Frame' data types and layouts (by TLV type) - frameformats.h )
Definition: frame.h:45
Provides definitions for using our generic TLV capabilities.
GSList * framelist
List of frames in this FrameSet.
Definition: frameset.h:47
gsize(* dataspace)(const Frame *self)
How much space is needed to marshall this Frame?
Definition: frame.h:48
void frameset_prepend_frame(FrameSet *fs, Frame *f)
Prepend frame to the front of the frame list.
Definition: frameset.c:132
#define FRAMETYPE_END
FRAMETYPE_END Frame (frametype 0) Frame subclass - Frame class.
Definition: frametypes.h:63
void(* updatedata)(Frame *self, gpointer tlvptr, gconstpointer pktend, FrameSet *fs)
Update packet data.
Definition: frame.h:49
FrameSet class - used for collecting Frames when not on the wire, and for marshalling/demarshalling t...
Definition: frameset.h:45
gchar *(* toString)(gconstpointer)
Produce malloc-ed string representation.
Definition: assimobj.h:58
#define FRAMETYPE_SIG
FRAMETYPE_SIG Frame (frametype 1) Frame subclass - SignFrame class.
Definition: frametypes.h:82
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
FSTATIC SeqnoFrame * _frameset_getseqno(FrameSet *self)
Definition: frameset.c:367
#define FRAMESET_INITSIZE
Definition: frameset.h:56
#define UNREF2(obj)
Definition: assimobj.h:36
#define FRAMETYPE_COMPRESS
FRAMETYPE_COMPRESS Frame (frametype 3) Frame subclass - CompressFrame class.
Definition: frametypes.h:116
#define CASTTOCLASS(Cclass, obj)
Safely cast 'obj' to C-class 'class' - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
#define UNREF(obj)
Definition: assimobj.h:35
#define NEWSUBCLASS(Cclass, obj)
Definition: proj_classes.h:67
This is an SeqnoFrame class TLV (type, length, value) frame.
Definition: seqnoframe.h:43
#define FRAMETYPE_REQID
FRAMETYPE_REQID Frame (frametype 4) Frame subclass - SeqnoFrame class.
Definition: frametypes.h:132