The Assimilation Project  based on Assimilation version 0.5.1427809010
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules 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_CRYPTCURVE28819 == (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  CryptFrame* 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  const gsize fssize = FRAMESET_INITSIZE; // "frameset" overhead size
172  guint32 computed_size;
173  DEBUGMSG3("%s.%d: constructing packet: sign: %p crypt: %p", __FUNCTION__, __LINE__, sigframe, cryptframe);
174  g_return_if_fail(NULL != fs);
175  g_return_if_fail(NULL != sigframe);
176  // g_return_if_fail(NULL != fs->framelist); // Is an empty frame list OK?
177 
178  /*
179  * The general method we employ here is to:
180  * 1. Free the current packet, if any
181  * 2. Remove current Framelist signature, compression, and encryption frames (if any).
182  * 3. Prepend a compression Frame if compm != NULL
183  * 4. Prepend an encryption Frame if cryptm != NULL
184  * 5. Prepend a signature Frame (sigm may not be NULL).
185  * 6. Figure out how much space we think we need to malloc for the packet using Frames.
186  * 7. Malloc enough space.
187  * 8. Populate all the frames into this new packet in reverse order.
188  */
189 
190  // Free current packet, if any...
191  if (fs->packet) {
192  FREE(fs->packet);
193  fs->packet = NULL;
194  fs->pktend = NULL;
195  }
196  // Remove any current signature, compression, or encryption frames...
197  // (this method only works if they're first, and all together - but that's OK)
198  while (fs->framelist) {
199  Frame* item = CASTTOCLASS(Frame, fs->framelist->data);
200  g_return_if_fail(NULL != item);
201  switch (item->type) {
202  case FRAMETYPE_SIG:
204  case FRAMETYPE_COMPRESS:
205  UNREF(item);
206  fs->framelist->data = NULL;
207  fs->framelist = g_slist_delete_link(fs->framelist, fs->framelist);
208  continue;
209  }
210  break;
211  }
232  if (NULL != compressframe) {
233  gsize estsize = FRAMESET_INITSIZE;
234  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
235  Frame* frame = CASTTOCLASS(Frame, curframe->data);
236  estsize += frame->dataspace(frame);
237  }
238  if (estsize > compressframe->compression_threshold) {
239  CompressFrame* newframe
240  = compressframe_new(compressframe->baseclass.type, compressframe->compression_method);
241  frameset_prepend_frame(fs, &newframe->baseclass);
242  UNREF2(newframe);
243  }
244  }
245  if (NULL != cryptframe) {
246  DEBUGMSG3("%s.%d: prepending cryptframe: %p", __FUNCTION__, __LINE__, cryptframe);
247  frameset_prepend_frame(fs, &cryptframe->baseclass);
248  }
249  // "sigframe" cannot be NULL (see check above)
250  frameset_prepend_frame(fs, CASTTOCLASS(Frame, sigframe));
251 
252  // Reverse list...
253  fs->framelist = g_slist_reverse(fs->framelist);
254 
255  // Add "end" frame to the "end" - if not already present...
256  if (CASTTOCLASS(Frame, fs->framelist->data)->type != FRAMETYPE_END) {
257  Frame* endframe = frame_new(FRAMETYPE_END, 0);
258  DEBUGMSG3("%s.%d: Adding FRAMETYPE_END frame to end (beginning)", __FUNCTION__, __LINE__);
259  g_return_if_fail(NULL != endframe);
260  frameset_prepend_frame(fs, endframe);
261  UNREF(endframe);
262  }
263 
264  pktsize = fssize;
265  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
266  Frame* frame = CASTTOCLASS(Frame, curframe->data);
267  pktsize += frame->dataspace(frame);
268  }
269  fs->packet = MALLOC0(pktsize);
270  fs->pktend = ((guint8*)fs->packet + pktsize);
271  g_return_if_fail(fs->packet != NULL);
272 
273  curpktoffset = pktsize;
274 
275  // Marshall out all our data - in reverse order...
276  // WATCH OUT: compression and encryption can replace or modify our packet(!)
277  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
278  Frame* frame = CASTTOCLASS(Frame, curframe->data);
279 
280  DUMP4(__FUNCTION__, &frame->baseclass, " is frame being processed");
281  // frame->dataspace() may change after calling updatedata()
282  curpktoffset = curpktoffset - frame->dataspace(frame);
283  g_return_if_fail(curpktoffset >= 0);
284  curpktpos = (guint8*)fs->packet + curpktoffset;
285  set_generic_tlv_type(curpktpos, frame->type, fs->pktend);
286  set_generic_tlv_len(curpktpos, frame->length, fs->pktend);
287  DUMP4(__FUNCTION__, &frame->baseclass, ": called frame->updatedata()");
288  frame->updatedata(frame, curpktpos, fs->pktend, fs);
289  // updatedata() can change fs->packet and fs->pktend
290  curpktpos = (guint8*)fs->packet + curpktoffset;
291  if (!frame->isvalid(frame, curpktpos, fs->pktend)) {
292  DUMP(__FUNCTION__, &frame->baseclass, " is an invalid frame");
293  g_warning("Generated %s frame is not valid(!) (length=%"G_GSIZE_FORMAT")"
294  , proj_class_classname(frame), (gsize)frame->length);
295  }
296  DUMP4(__FUNCTION__, &frame->baseclass, " is frame that was processed.");
297  }
298  DUMP4(__FUNCTION__, &fs->baseclass, " is frameset that was processed");
299  g_return_if_fail(curpktpos == (((guint8*)fs->packet)+fssize));
300  // Reverse list - putting it back in the right order
301  fs->framelist = g_slist_reverse(fs->framelist);
302  // Write out the initial FrameSet header.
303  set_generic_tlv_type(fs->packet, fs->fstype, ((guint8*)fs->packet)+fssize);
304  computed_size = ((guint8*)fs->pktend-(guint8*)fs->packet)-fssize;
305  set_generic_tlv_len(fs->packet, computed_size, ((guint8*)fs->packet)+fssize);
306  tlv_set_guint16(((guint8*)fs->packet)+GENERICTLV_HDRSZ, fs->fsflags, ((guint8*)fs->packet)+fssize);
307  DEBUGMSG3("%s.%d: Returning.", __FUNCTION__, __LINE__);
308 }
309 
311 guint16
313 {
314  g_return_val_if_fail(NULL != fs, 0xffff);
315  return fs->fsflags;
316 }
317 
319 guint16
321  guint16 flagbits)
322 {
323  g_return_val_if_fail(NULL != fs, 0xffff);
324  fs->fsflags |= flagbits;
325  return fs->fsflags;
326 }
327 
329 guint16
331  guint16 flagbits)
332 {
333  g_return_val_if_fail(NULL != fs, 0xffff);
334  g_return_val_if_fail(flagbits != 0x0000, fs->fsflags);
335  fs->fsflags &= ~flagbits;
336  return fs->fsflags;
337 }
338 
341 gpointer
343  Frame* f,
344  gpointer curpktpos)
345 {
346  guint8 * curpos = curpktpos;
347  guint8 * endpos = fs->pktend;
348 
349  g_return_val_if_fail(fs != NULL && f != NULL && fs->packet != NULL && curpktpos != NULL, NULL);
350  g_return_val_if_fail((curpos + f->dataspace(f)) <= endpos, NULL);
351 
352  tlv_set_guint16(curpos, f->type, fs->pktend);
353  curpos += 2; // sizeof(guint16)
354  tlv_set_guint24(curpos, f->length, fs->pktend);
355  curpos += 3; // 3 byte integer for length
356  if (f->length > 0) {
357  // Zero-length frames are just fine.
358  memcpy(curpos, f->value, f->length);
359  }
360  curpos += f->length;
361  return (gpointer)curpos;
362 }
363 
365 void
367 {
368  GSList* curframe;
369  g_debug("BEGIN Dumping FrameSet:");
370  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
371  Frame* frame = CASTTOCLASS(Frame, curframe->data);
372  frame->dump(frame, ".... ");
373  }
374  g_debug("END FrameSet dump");
375 }
376 
379 {
380  GSList* curframe;
381  int j = 0;
382  if (self->_seqframe) {
383  return self->_seqframe;
384  }
385  if (self->fstype < MIN_SEQFRAMESET) {
386  return NULL;
387  }
388  DEBUGMSG4("%s.%d: frameset type %d", __FUNCTION__, __LINE__, self->fstype);
389  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
390  Frame* frame = CASTTOCLASS(Frame, curframe->data);
391  j += 1;
392  DEBUGMSG4("%s.%d: LOOKING AT FRAME %d TYPE %d (but want sequence number [%d])"
393  , __FUNCTION__, __LINE__, j, frame->type, FRAMETYPE_REQID);
394  if (frame->type == FRAMETYPE_REQID) {
395  self->_seqframe = CASTTOCLASS(SeqnoFrame, frame);
396  DEBUGMSG4("%s.%d: GOT sequence number [%ld])"
397  , __FUNCTION__, __LINE__, (long)self->_seqframe->_reqid);
398  return self->_seqframe;
399  }
400  }
401  return NULL;
402 }
403 
404 FSTATIC char *
405 _frameset_toString(gconstpointer vself)
406 {
407  GString* gsret = NULL;
408  char* ret = NULL;
409  const FrameSet* self = CASTTOCONSTCLASS(FrameSet, vself);
410  GSList* curframe;
411  const char * comma = "";
412 
413  g_return_val_if_fail(self != NULL, NULL);
414  gsret = g_string_new("");
415  g_string_append_printf(gsret, "FrameSet(fstype=%d, [", self->fstype);
416 
417  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
418  Frame* frame = CASTTOCLASS(Frame, curframe->data);
419  char* fstr;
420  g_return_val_if_fail(frame != NULL, NULL);
421  fstr = frame->baseclass.toString(&frame->baseclass);
422  g_string_append_printf(gsret, "%s[%s]", comma, fstr);
423  comma = ", ";
424  g_free(fstr); fstr = NULL;
425  }
426  g_string_append_printf(gsret, "])");
427  ret = gsret->str;
428  g_string_free(gsret, FALSE);
429  return ret;
430 }
431 
432 
434 WINEXPORT const char *
436 {
437  gpointer maybecrypt;
438  CryptFrame* cryptframe;
439 
440  // If we have an encryption frame it *must* be the second frame
441  // (the first frame is frame 0, and the second is frame 1)
442  maybecrypt = g_slist_nth_data(self->framelist, 1);
443  if (!maybecrypt || !OBJ_IS_A(maybecrypt, "CryptFrame")) {
444  return NULL;
445  }
446  cryptframe = CASTTOCLASS(CryptFrame, maybecrypt);
447  return cryptframe->sender_key_id;
448 }
449 
451 WINEXPORT const char *
453 {
455 }
456 
#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:320
void frameset_dump(const FrameSet *fs)
Dump out a FrameSet.
Definition: frameset.c:366
AssimObj baseclass
Definition: frameset.h:47
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:312
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:330
#define DEBUGMSG4(...)
Definition: proj_classes.h:92
AssimObj baseclass
Base object class for our Class system.
Definition: frame.h:44
char * sender_key_id
Definition: cryptframe.h:55
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:55
FSTATIC char * _frameset_toString(gconstpointer)
Definition: frameset.c:405
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:47
WINEXPORT const char * frameset_sender_identity(const FrameSet *self)
Return the identity of this Frameset's CryptFrame sender – NULL if None or Unknown.
Definition: frameset.c:452
gpointer pktend
Last byte past the end of the packet.
Definition: frameset.h:51
gpointer frame_append_to_frameset_packet(FrameSet *fs, Frame *f, gpointer curpktpos)
Append the given Frame to a FrameSet packet.
Definition: frameset.c:342
#define WINEXPORT
Definition: projectcommon.h:45
#define FSTATIC
Definition: projectcommon.h:31
#define DEBUGMSG3(...)
Definition: proj_classes.h:91
#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:52
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:148
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:67
#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
WINEXPORT const char * cryptframe_whois_key_id(const char *key_id)
Return the identity associated with the given key id.
Definition: cryptframe.c:371
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:125
#define OBJ_IS_A(obj, Cclass)
Definition: proj_classes.h:72
gboolean(* isvalid)(const Frame *self, gconstpointer tlvptr, gconstpointer pktend)
TRUE if TLV data looks valid...
Definition: frame.h:50
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:50
#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.
WINEXPORT const char * frameset_sender_key_id(const FrameSet *self)
Return the key_id of this Frameset's CryptFrame sender – NULL if None.
Definition: frameset.c:435
Header file defining the data layouts for our Frames.
TLV helper interfaces definitions.
Frame baseclass
Definition: cryptframe.h:54
guint8 compression_method
Definition: compressframe.h:45
guint16 fsflags
Flags for frameset.
Definition: frameset.h:53
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:48
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 DUMP(prefix, obj, suffix)
Definition: proj_classes.h:94
void frameset_construct_packet(FrameSet *fs, SignFrame *sigframe, CryptFrame *cryptframe, CompressFrame *compressframe)
Construct packet to go correspond to this frameset.
Definition: frameset.c:159
#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:46
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 MIN_SEQFRAMESET
First frameset type with a sequence number.
Definition: framesettypes.h:65
#define DEBUGDECLARATIONS
Definition: proj_classes.h:79
FSTATIC SeqnoFrame * _frameset_getseqno(FrameSet *self)
Definition: frameset.c:378
This is our CryptFrame class object - representing an encryption method.
Definition: cryptframe.h:53
#define FRAMESET_INITSIZE
Definition: frameset.h:57
#define DUMP4(prefix, obj, suffix)
Definition: proj_classes.h:98
#define UNREF2(obj)
Definition: assimobj.h:36
#define FRAMETYPE_COMPRESS
FRAMETYPE_COMPRESS Frame (frametype 3) Frame subclass - CompressFrame class.
Definition: frametypes.h:122
#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:138
#define FRAMETYPE_CRYPTCURVE25519
FRAMETYPE_CRYPTCURVE25519 Frame (frametype 2) Frame subclass - CryptCurve25519 class.
Definition: frametypes.h:104