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 <generic_tlv_min.h>
56 #include <tlvhelper.h>
57 FSTATIC void _frameset_indir_finalize(void* f);
59 FSTATIC char * _frameset_toString(gconstpointer);
60 
62 
69 
71 
73 FSTATIC void
75 {
76  Frame* frame = CASTTOCLASS(Frame, f);
77  UNREF(frame);
78 }
79 
81 FSTATIC void
83 {
84  FrameSet* fs = CASTTOCLASS(FrameSet, obj);
85  g_return_if_fail(NULL != fs);
88  if (fs->framelist) {
89  // Would rather use g_slist_free_full() - but it's too new to be widely deployed...
90  while (NULL != fs->framelist) {
92  fs->framelist->data = NULL;
93  fs->framelist = g_slist_delete_link(fs->framelist, fs->framelist);
94  }
95  }
96  if (fs->packet) {
97  FREE(fs->packet);
98  fs->packet = NULL;
99  fs->pktend = NULL;
100  }
101  memset(fs, 0x0, sizeof(*fs));
102  FREECLASSOBJ(fs);
103 }
104 
105 
106 
108 FrameSet*
109 frameset_new(guint16 frameset_type)
110 {
111  AssimObj* obj = assimobj_new(sizeof(FrameSet));
112  FrameSet* s = NEWSUBCLASS(FrameSet, obj);
113 
115  g_return_val_if_fail(s != NULL, NULL);
116  s->fstype = frameset_type;
117  s->framelist = NULL;
118  s->packet = NULL;
119  s->pktend = NULL;
120  s->fsflags = 0;
124  return s;
125 }
126 
128 void
130  Frame* f)
131 {
132  g_return_if_fail(NULL != fs && NULL != f);
133  REF(f);
134  fs->framelist = g_slist_prepend(fs->framelist, f);
135 }
136 
138 void
140  Frame* f)
141 {
142  g_return_if_fail(NULL != fs && NULL != f);
143  REF(f);
144  fs->framelist = g_slist_append(fs->framelist, f);
145 }
146 
154 void
156  SignFrame* sigframe,
157  Frame* cryptframe,
158  Frame* compressframe)
160 {
163  GSList* curframe; // Current frame as we marshall packet...
164  gpointer curpktpos; // Current position as we marshall packet...
165  gsize pktsize;
166  gsize fssize = FRAMESET_INITSIZE; // "frameset" overhead size
167  g_return_if_fail(NULL != fs);
168  g_return_if_fail(NULL != sigframe);
169  // g_return_if_fail(NULL != fs->framelist); // Is an empty frame list OK?
170 
171  /*
172  * The general method we employ here is to:
173  * 1. Free the current packet, if any
174  * 2. Remove current Framelist signature, compression, and encryption frames (if any).
175  * 3. Prepend a compression Frame if compm != NULL
176  * 4. Prepend an encryption Frame if cryptm != NULL
177  * 5. Prepend a signature Frame (sigm may not be NULL).
178  * 6. Figure out how much space we think we need to malloc for the packet using Frames.
179  * 7. Malloc enough space.
180  * 8. Populate all the frames into this new packet in reverse order.
181  */
182 
183  // Free current packet, if any...
184  if (fs->packet) {
185  FREE(fs->packet);
186  fs->packet = NULL;
187  fs->pktend = NULL;
188  }
189  // Remove any current signature, compression, or encryption frames...
190  // (this method only works if they're first, and all together - but that's OK)
191  while (fs->framelist) {
192  Frame* item = CASTTOCLASS(Frame, fs->framelist->data);
193  g_return_if_fail(NULL != item);
194  switch (item->type) {
195  case FRAMETYPE_SIG:
196  case FRAMETYPE_CRYPT:
197  case FRAMETYPE_COMPRESS:
198  UNREF(item);
199  fs->framelist->data = NULL;
200  fs->framelist = g_slist_delete_link(fs->framelist, fs->framelist);
201  continue;
202  }
203  break;
204  }
225  if (NULL != compressframe) {
226  frameset_prepend_frame(fs, compressframe);
227  }
228  if (NULL != cryptframe) {
229  frameset_prepend_frame(fs, cryptframe);
230  }
231  // "sigframe" cannot be NULL (see check above)
232  frameset_prepend_frame(fs, CASTTOCLASS(Frame, sigframe));
233 
234  // Reverse list...
235  fs->framelist = g_slist_reverse(fs->framelist);
236 
237  // Add "end" frame to the "end" - if not already present...
238  if (CASTTOCLASS(Frame, fs->framelist->data)->type != FRAMETYPE_END) {
239  Frame* endframe = frame_new(FRAMETYPE_END, 0);
240  g_return_if_fail(NULL != endframe);
241  frameset_prepend_frame(fs, endframe);
242  UNREF(endframe);
243  }
244 
245  pktsize = fssize;
246  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
247  Frame* frame = CASTTOCLASS(Frame, curframe->data);
248  pktsize += frame->dataspace(frame);
249  }
250  fs->packet = MALLOC0(pktsize);
251  fs->pktend = ((guint8*)fs->packet + pktsize);
252  g_return_if_fail(fs->packet != NULL);
253 
254  curpktpos = fs->pktend;
255 
256  // Marshall out all our data - in reverse order...
257  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
258  Frame* frame = CASTTOCLASS(Frame, curframe->data);
259 
260  curpktpos = ((guint8*)curpktpos) - frame->dataspace(frame);
261  g_return_if_fail(curpktpos >= fs->packet);
262  set_generic_tlv_type(curpktpos, frame->type, fs->pktend);
263  set_generic_tlv_len(curpktpos, frame->length, fs->pktend);
264  frame->updatedata(frame, curpktpos, fs->pktend, fs);
265  if (!frame->isvalid(frame, curpktpos, fs->pktend)) {
266  g_error("Generated %s frame is not valid(!)"
267  , proj_class_classname(frame));
268  }
269  }
270  g_return_if_fail(curpktpos == (((guint8*)fs->packet)+fssize));
271  // Reverse list - putting it back in the right order
272  fs->framelist = g_slist_reverse(fs->framelist);
273  // Write out the initial FrameSet header.
274  set_generic_tlv_type(fs->packet, fs->fstype, ((guint8*)fs->packet)+fssize);
275  set_generic_tlv_len(fs->packet, pktsize-fssize, ((guint8*)fs->packet)+fssize);
276  tlv_set_guint16(((guint8*)fs->packet)+GENERICTLV_HDRSZ, fs->fsflags, ((guint8*)fs->packet)+fssize);
277 }
278 
280 guint16
282 {
283  g_return_val_if_fail(NULL != fs, 0xffff);
284  return fs->fsflags;
285 }
286 
288 guint16
290  guint16 flagbits)
291 {
292  g_return_val_if_fail(NULL != fs, 0xffff);
293  fs->fsflags |= flagbits;
294  return fs->fsflags;
295 }
296 
298 guint16
300  guint16 flagbits)
301 {
302  g_return_val_if_fail(NULL != fs, 0xffff);
303  g_return_val_if_fail(flagbits != 0x0000, fs->fsflags);
304  fs->fsflags &= ~flagbits;
305  return fs->fsflags;
306 }
307 
310 gpointer
312  Frame* f,
313  gpointer curpktpos)
314 {
315  guint8 * curpos = curpktpos;
316  guint8 * endpos = fs->pktend;
317 
318  g_return_val_if_fail(fs != NULL && f != NULL && fs->packet != NULL && curpktpos != NULL, NULL);
319  g_return_val_if_fail((curpos + f->dataspace(f)) <= endpos, NULL);
320 
321  tlv_set_guint16(curpos, f->type, fs->pktend);
322  curpos += 2; // sizeof(guint16)
323  tlv_set_guint16(curpos, f->length, fs->pktend);
324  curpos += 2; // sizeof(guint16)
325  if (f->length > 0) {
326  // Zero-length frames are just fine.
327  memcpy(curpos, f->value, f->length);
328  }
329  curpos += f->length;
330  return (gpointer)curpos;
331 }
332 
334 void
336 {
337  GSList* curframe;
338  g_debug("BEGIN Dumping FrameSet:");
339  for (curframe=fs->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
340  Frame* frame = CASTTOCLASS(Frame, curframe->data);
341  frame->dump(frame, ".... ");
342  }
343  g_debug("END FrameSet dump");
344 }
345 
348 {
349  GSList* curframe;
350  if (self->_seqframe) {
351  return self->_seqframe;
352  }
353  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
354  Frame* frame = CASTTOCLASS(Frame, curframe->data);
355  DEBUGMSG4("%s: LOOKING AT FRAME TYPE %d (but want sequence number)", __FUNCTION__, frame->type);
356  if (frame->type == FRAMETYPE_REQID) {
357  self->_seqframe = CASTTOCLASS(SeqnoFrame, frame);
358  return self->_seqframe;
359  }
360  }
361  return NULL;
362 }
363 
364 FSTATIC char *
365 _frameset_toString(gconstpointer vself)
366 {
367  GString* gsret = NULL;
368  char* ret = NULL;
369  const FrameSet* self = CASTTOCONSTCLASS(FrameSet, vself);
370  GSList* curframe;
371  const char * comma = "";
372 
373  g_return_val_if_fail(self != NULL, NULL);
374  gsret = g_string_new("");
375  g_string_append_printf(gsret, "FrameSet(fstype=%d, [", self->fstype);
376 
377  for (curframe=self->framelist; curframe != NULL; curframe = g_slist_next(curframe)) {
378  Frame* frame = CASTTOCLASS(Frame, curframe->data);
379  char* fstr;
380  g_return_val_if_fail(frame != NULL, NULL);
381  fstr = frame->baseclass.toString(&frame->baseclass);
382  g_string_append_printf(gsret, "%s[%s]", comma, fstr);
383  comma = ", ";
384  g_free(fstr); fstr = NULL;
385  }
386  g_string_append_printf(gsret, "])");
387  ret = gsret->str;
388  g_string_free(gsret, FALSE);
389  return ret;
390 }
391