The Assimilation Project  based on Assimilation version 0.5.1435932971
 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  }
231  if (NULL != compressframe) {
232  gsize estsize = FRAMESET_INITSIZE;
233  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
234  Frame* frame = CASTTOCLASS(Frame, curframe->data);
235  estsize += frame->dataspace(frame);
236  }
237  if (estsize > compressframe->compression_threshold) {
238  CompressFrame* newframe
239  = compressframe_new(compressframe->baseclass.type, compressframe->compression_method);
240  frameset_prepend_frame(fs, &newframe->baseclass);
241  UNREF2(newframe);
242  }
243  }
244  if (NULL != cryptframe) {
245  DEBUGMSG3("%s.%d: prepending cryptframe: %p", __FUNCTION__, __LINE__, cryptframe);
246  frameset_prepend_frame(fs, &cryptframe->baseclass);
247  }
248  // "sigframe" cannot be NULL (see check above)
249  frameset_prepend_frame(fs, CASTTOCLASS(Frame, sigframe));
250 
251  // Reverse list...
252  fs->framelist = g_slist_reverse(fs->framelist);
253 
254  // Add "end" frame to the "end" - if not already present...
255  if (CASTTOCLASS(Frame, fs->framelist->data)->type != FRAMETYPE_END) {
256  Frame* endframe = frame_new(FRAMETYPE_END, 0);
257  DEBUGMSG3("%s.%d: Adding FRAMETYPE_END frame to end (beginning)", __FUNCTION__, __LINE__);
258  g_return_if_fail(NULL != endframe);
259  frameset_prepend_frame(fs, endframe);
260  UNREF(endframe);
261  }
262 
263  pktsize = fssize;
264  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
265  Frame* frame = CASTTOCLASS(Frame, curframe->data);
266  pktsize += frame->dataspace(frame);
267  }
268  fs->packet = MALLOC0(pktsize);
269  fs->pktend = ((guint8*)fs->packet + pktsize);
270  g_return_if_fail(fs->packet != NULL);
271 
272  curpktoffset = pktsize;
273 
274  // Marshall out all our data - in reverse order...
275  // WATCH OUT: compression and encryption can replace or modify our packet(!)
276  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
277  Frame* frame = CASTTOCLASS(Frame, curframe->data);
278 
279  DUMP4(__FUNCTION__, &frame->baseclass, " is frame being processed");
280  // frame->dataspace() may change after calling updatedata()
281  curpktoffset = curpktoffset - frame->dataspace(frame);
282  g_return_if_fail(curpktoffset >= 0);
283  curpktpos = (guint8*)fs->packet + curpktoffset;
284  set_generic_tlv_type(curpktpos, frame->type, fs->pktend);
285  set_generic_tlv_len(curpktpos, frame->length, fs->pktend);
286  DUMP4(__FUNCTION__, &frame->baseclass, ": calling frame->updatedata()");
287  frame->updatedata(frame, curpktpos, fs->pktend, fs);
288  // updatedata() can change fs->packet and fs->pktend
289  curpktpos = (guint8*)fs->packet + curpktoffset;
290  if (!frame->isvalid(frame, curpktpos, fs->pktend)) {
291  DUMP(__FUNCTION__, &frame->baseclass, " is an invalid frame");
292  g_warning("Generated %s frame is not valid(!) (length=%"G_GSIZE_FORMAT")"
293  , proj_class_classname(frame), (gsize)frame->length);
294  }
295  DUMP4(__FUNCTION__, &frame->baseclass, " is frame that was processed.");
296  }
297  DUMP4(__FUNCTION__, &fs->baseclass, " is frameset that was processed");
298  g_return_if_fail(curpktpos == (((guint8*)fs->packet)+fssize));
299  // Reverse list - putting it back in the right order
300  fs->framelist = g_slist_reverse(fs->framelist);
301  // Write out the initial FrameSet header.
302  set_generic_tlv_type(fs->packet, fs->fstype, ((guint8*)fs->packet)+fssize);
303  computed_size = ((guint8*)fs->pktend-(guint8*)fs->packet)-fssize;
304  set_generic_tlv_len(fs->packet, computed_size, ((guint8*)fs->packet)+fssize);
305  tlv_set_guint16(((guint8*)fs->packet)+GENERICTLV_HDRSZ, fs->fsflags, ((guint8*)fs->packet)+fssize);
306  DEBUGMSG3("%s.%d: Returning.", __FUNCTION__, __LINE__);
307 }
308 
310 guint16
312 {
313  g_return_val_if_fail(NULL != fs, 0xffff);
314  return fs->fsflags;
315 }
316 
318 guint16
320  guint16 flagbits)
321 {
322  g_return_val_if_fail(NULL != fs, 0xffff);
323  fs->fsflags |= flagbits;
324  return fs->fsflags;
325 }
326 
328 guint16
330  guint16 flagbits)
331 {
332  g_return_val_if_fail(NULL != fs, 0xffff);
333  g_return_val_if_fail(flagbits != 0x0000, fs->fsflags);
334  fs->fsflags &= ~flagbits;
335  return fs->fsflags;
336 }
337 
340 gpointer
342  Frame* f,
343  gpointer curpktpos)
344 {
345  guint8 * curpos = curpktpos;
346  guint8 * endpos = fs->pktend;
347 
348  g_return_val_if_fail(fs != NULL && f != NULL && fs->packet != NULL && curpktpos != NULL, NULL);
349  g_return_val_if_fail((curpos + f->dataspace(f)) <= endpos, NULL);
350 
351  tlv_set_guint16(curpos, f->type, fs->pktend);
352  curpos += 2; // sizeof(guint16)
353  tlv_set_guint24(curpos, f->length, fs->pktend);
354  curpos += 3; // 3 byte integer for length
355  if (f->length > 0) {
356  // Zero-length frames are just fine.
357  memcpy(curpos, f->value, f->length);
358  }
359  curpos += f->length;
360  return (gpointer)curpos;
361 }
362 
364 void
366 {
367  GSList* curframe;
368  g_debug("BEGIN Dumping FrameSet:");
369  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
370  Frame* frame = CASTTOCLASS(Frame, curframe->data);
371  frame->dump(frame, ".... ");
372  }
373  g_debug("END FrameSet dump");
374 }
375 
378 {
379  GSList* curframe;
380  int j = 0;
381  if (self->_seqframe) {
382  return self->_seqframe;
383  }
384  if (self->fstype < MIN_SEQFRAMESET) {
385  return NULL;
386  }
387  DEBUGMSG4("%s.%d: frameset type %d", __FUNCTION__, __LINE__, self->fstype);
388  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
389  Frame* frame = CASTTOCLASS(Frame, curframe->data);
390  j += 1;
391  DEBUGMSG4("%s.%d: LOOKING AT FRAME %d TYPE %d (but want sequence number [%d])"
392  , __FUNCTION__, __LINE__, j, frame->type, FRAMETYPE_REQID);
393  if (frame->type == FRAMETYPE_REQID) {
394  self->_seqframe = CASTTOCLASS(SeqnoFrame, frame);
395  DEBUGMSG4("%s.%d: GOT sequence number [%ld])"
396  , __FUNCTION__, __LINE__, (long)self->_seqframe->_reqid);
397  return self->_seqframe;
398  }
399  }
400  return NULL;
401 }
402 
403 FSTATIC char *
404 _frameset_toString(gconstpointer vself)
405 {
406  GString* gsret = NULL;
407  char* ret = NULL;
408  const FrameSet* self = CASTTOCONSTCLASS(FrameSet, vself);
409  GSList* curframe;
410  const char * comma = "";
411 
412  g_return_val_if_fail(self != NULL, NULL);
413  gsret = g_string_new("");
414  g_string_append_printf(gsret, "FrameSet(fstype=%d, [", self->fstype);
415 
416  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
417  Frame* frame = CASTTOCLASS(Frame, curframe->data);
418  char* fstr;
419  g_return_val_if_fail(frame != NULL, NULL);
420  fstr = frame->baseclass.toString(&frame->baseclass);
421  g_string_append_printf(gsret, "%s[%s]", comma, fstr);
422  comma = ", ";
423  g_free(fstr); fstr = NULL;
424  }
425  g_string_append_printf(gsret, "])");
426  ret = gsret->str;
427  g_string_free(gsret, FALSE);
428  return ret;
429 }
430 
431 
433 WINEXPORT const char *
435 {
436  gpointer maybecrypt;
437  CryptFrame* cryptframe;
438 
439  // If we have an encryption frame it *must* be the second frame
440  // (the first frame is frame 0, and the second is frame 1)
441  maybecrypt = g_slist_nth_data(self->framelist, 1);
442  if (!maybecrypt || !OBJ_IS_A(maybecrypt, "CryptFrame")) {
443  return NULL;
444  }
445  cryptframe = CASTTOCLASS(CryptFrame, maybecrypt);
446  return cryptframe->sender_key_id;
447 }
448 
450 WINEXPORT const char *
452 {
454 }
455 
#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:319
void frameset_dump(const FrameSet *fs)
Dump out a FrameSet.
Definition: frameset.c:365
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:311
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:329
#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:404
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:451
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:341
#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:434
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:377
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