aboutsummaryrefslogtreecommitdiffstats
path: root/range.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2003-12-29 22:43:33 +0000
committerGuy Harris <guy@alum.mit.edu>2003-12-29 22:43:33 +0000
commitd177c7d7310fcfdaaba89c4186395991c8f28f97 (patch)
tree302f9521526f114270ac1e24e6be4cf6ce1af42d /range.c
parent1479458d1b1f895dbcefb9329275787c7e1e489d (diff)
Nothing in "range.c" is GTK+-specific, so move it to the top-level
directory. svn path=/trunk/; revision=9487
Diffstat (limited to 'range.c')
-rw-r--r--range.c389
1 files changed, 389 insertions, 0 deletions
diff --git a/range.c b/range.c
new file mode 100644
index 0000000000..0e4c1c2c65
--- /dev/null
+++ b/range.c
@@ -0,0 +1,389 @@
+/* range.c
+ * Packet range routines (save, print, ...)
+ *
+ * $Id: range.c,v 1.1 2003/12/29 22:42:39 guy Exp $
+ *
+ * Dick Gooris <gooris@lucent.com>
+ * Ulf Lamping <ulf.lamping@web.de>
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+
+#include <glib.h>
+
+#include <epan/frame_data.h>
+
+
+#include "range.h"
+
+#include "globals.h"
+
+
+static gboolean packet_is_in_range(guint32 val);
+
+
+/* Range parser variables */
+#define MaxRange 30
+
+struct range_admin {
+ guint32 low;
+ guint32 high;
+};
+
+static guint GLnrange=0;
+struct range_admin GLrange[MaxRange];
+static guint32 max_packets;
+
+void packet_range_init(packet_range_t *range) {
+ guint32 current_count;
+ guint32 displayed_count;
+ guint32 mark_low;
+ guint32 mark_high;
+ frame_data *packet;
+
+ /* This is needed to calculate the number of packets for each variation
+ * like the total amount of packets, the number of marked packets, and
+ * the number between the packets. This is for information only
+ */
+
+ /* "enumeration" values */
+ range->markers = cfile.marked_count;
+ range->range_active = FALSE;
+ range->process_curr_done = FALSE;
+
+ displayed_count = 0L;
+ mark_low = 0L;
+ mark_high = 0L;
+ range->mark_range = 0L;
+
+ current_count = 0;
+ for(packet = cfile.plist; packet != NULL; packet = packet->next) {
+ current_count++;
+ if (cfile.current_frame == packet) {
+ range->selected_packet = current_count;
+ }
+ if (packet->flags.passed_dfilter) {
+ displayed_count++;
+ }
+ if (packet->flags.marked) {
+ if (mark_low == 0) {
+ mark_low = current_count;
+ }
+ if (current_count > mark_high) {
+ mark_high = current_count;
+ }
+ }
+ }
+ /* in case we marked just one packet, we add 1. */
+ if (cfile.marked_count != 0) {
+ range->mark_range = mark_high - mark_low + 1;
+ }
+ /* make this global, to be used in function conv_str_range() */
+ max_packets = cfile.count;
+}
+
+
+/* do we have to process all packets? */
+gboolean packet_range_process_all(packet_range_t *range) {
+ return range->process_all && !range->process_filtered;
+}
+
+/* do we have to process this packet? */
+range_process_e packet_range_process(packet_range_t *range, frame_data *fdata) {
+
+ /* do we have to process this packet at all? */
+ if (
+ (!range->process_filtered && !range->process_marked) ||
+ (range->process_filtered && fdata->flags.passed_dfilter && !range->process_marked) ||
+ (range->process_marked && fdata->flags.marked && !range->process_filtered) ||
+ (range->process_filtered && range->process_marked && fdata->flags.passed_dfilter && fdata->flags.marked) ||
+ (range->process_curr) ||
+ (range->process_marked_range) ||
+ (range->process_manual_range) ||
+ (range->range_active)
+ ) {
+ /* yes, we have to */
+ } else {
+ return range_process_next;
+ }
+
+ /* In case we process a manual range, we check the packet number
+ * with the range as defined in the array GLrange, see file_dlg.c
+ * If a match is found, we process it, otherwise we simply go to check
+ * the next packet.
+ */
+ if (range->process_manual_range) {
+ if (range->process_filtered) {
+ if (fdata->flags.passed_dfilter == FALSE) {
+ return range_process_next;
+ }
+ }
+ if (packet_is_in_range(fdata->num) == FALSE) {
+ return range_process_next;
+ }
+ }
+
+ /* For processing a marked range, skip the frames not marked in the first place
+ * until the first marked frame comes by. Then continue processing until we found the
+ * last marked frame. We set the range_active to FALSE in the first place until
+ * a marked frame is found (fdata->flags.marked == TRUE) From now on range_active
+ * is TRUE, and the large 'if' statement will pass by any frame. It will stop doing
+ * so once the markers count got 0. process_marked_range got set in gtk/file_dlg.c
+ */
+ if (range->process_marked_range) {
+ if (range->markers == 0) {
+ return range_processing_finished;
+ }
+ if (fdata->flags.marked == TRUE) {
+ range->range_active = TRUE;
+ range->markers--;
+ }
+ if (range->process_filtered) {
+ if (fdata->flags.passed_dfilter == FALSE) {
+ return range_process_next;
+ }
+ }
+ if (range->range_active == FALSE ) {
+ return range_process_next;
+ }
+ }
+
+ /* Only process the selected frame. If accomplished, finish */
+ if (range->process_curr) {
+ if (range->process_curr_done) {
+ return range_processing_finished;
+ }
+ if (fdata->num != cfile.current_frame->num) {
+ return range_process_next;
+ }
+ range->process_curr_done = TRUE;
+ }
+
+ return range_process_this;
+}
+
+
+
+
+/******************** Range Entry Parser *********************************/
+
+/* Convert the entry range string in a fast comparable array of ranges.
+ * In the first place get rid of spaces, and any other characters than
+ * commas, digits, and hyphens. The parameter es points to the string to be processed
+ *
+ * This function is only called once when a range string is provided in the Save/Print As
+ * widget. This function fills an array of low and high values indexed by a global
+ * varaiable GLnrange. After having called this function, the function isin(val)
+ * determines whether the value is with the range or not.
+ */
+
+void packet_range_convert_str(const gchar *es)
+{
+ gchar EntryStr[255], OrgStr[255], value[255], p;
+ guint i, j=0;
+ guint32 tmp, val;
+ gboolean hyphenseen;
+
+ /* Reset the number of ranges we are going to find */
+ GLnrange = 0;
+ GLrange[GLnrange].low = 0L;
+ GLrange[GLnrange].high = 0L;
+
+ /* Make a copy of the string, and check the validity of the input */
+ strcpy(OrgStr,es);
+ if (strlen(OrgStr) == 0 ) {
+ return;
+ }
+
+ /* only keep digits, commas, and hyphens. */
+ for (i=0; i<=strlen(OrgStr); i++) {
+ if ( isdigit(OrgStr[i]) || OrgStr[i] == '-' || OrgStr[i] == ',' ) {
+ EntryStr[j++] = OrgStr[i];
+ }
+ }
+ EntryStr[j] = '\0';
+
+ /* remove any starting commas */
+ strcpy(OrgStr,EntryStr);
+ i = 0;
+ while (OrgStr[i] == ',') {
+ i++;
+ }
+ strcpy(EntryStr,OrgStr+i);
+
+ /* remove any double commas within the entry string */
+ strcpy(OrgStr,EntryStr);
+ p = ',';
+ j = 0;
+ for (i=0; i<=strlen(OrgStr); i++) {
+ if ( OrgStr[i] != ',' || p != ',') {
+ EntryStr[j++] = OrgStr[i];
+ }
+ p = OrgStr[i];
+ }
+ EntryStr[j] = '\0';
+
+ /* remove any double hyphens within the entry string */
+ strcpy(OrgStr,EntryStr);
+ p = '-';
+ j = 0;
+ for (i=0; i<=strlen(OrgStr); i++) {
+ if (OrgStr[i] != '-' || p != '-' || i == 0) {
+ EntryStr[j++] = OrgStr[i];
+ }
+ p = OrgStr[i];
+ }
+ EntryStr[j] = '\0';
+
+ /* remove any trailing commas */
+ i = strlen(EntryStr) - 1;
+ while (EntryStr[i] == ',') {
+ EntryStr[i] = '\0';
+ i--;
+ }
+
+ /* The entry string is now filtered, and ready for further parsing */
+ /* printf("str=%s\n",EntryStr); */
+
+ /* Now we are going to process the ranges separately until we get a comma,
+ * or end of string. The following input are interpreted all right :
+ *
+ * 0-20,30-40 -=> Range from 0 to 20, and packets 30 to 40
+ * -20,30 -=> Range from 0 to 20, and packet 30
+ * 20,30,40- -=> Packet number 20, 30, and the range from 40 to the end
+ * 20-10,30-25 -=> Range from 10 to 20, and from 25 to 30
+ * - -=> All packets
+ *
+ * We build a structure array called GLrange of high and low values. After the
+ * following loop, we have the GLnrange variable which tells how many ranges
+ * are found.
+ * The number of different ranges is limited to 'MaxRanges'
+ */
+
+ j = 0;
+ hyphenseen = FALSE;
+ for (i=0; i<=strlen(EntryStr);i++) {
+
+ /* copy the digit string until a no-digit character is seen */
+ if (isdigit(EntryStr[i])) {
+ value[j++] = EntryStr[i];
+ continue;
+ }
+
+ /* Terminate the digit string, and convert it */
+ value[j] = '\0';
+ val=atol(value);
+ j=0;
+
+ /* treatment in case we see a hyphen */
+ if (EntryStr[i] == '-') {
+ /* if this is a trailer hyphen, then treat it in a different
+ * way, then the high value is the maximum number of packets counted
+ * and we are ready */
+ if (i == strlen(EntryStr)-1) {
+ GLrange[GLnrange].low = val;
+ GLrange[GLnrange].high = max_packets;
+ GLnrange++;
+ break;
+ } else {
+ /* if no digits were actually seen, the outcome of
+ * a zeroed string conversion to interger is also 0. */
+ GLrange[GLnrange].low = val;
+ }
+ hyphenseen=TRUE;
+ continue;
+ }
+
+ /* treatment in case we see a comma, or end of string */
+ if (EntryStr[i] == ',' || i == strlen(EntryStr)) {
+ if (hyphenseen) {
+ GLrange[GLnrange].high = val;
+ } else {
+ /* in this case we got a single packet number */
+ GLrange[GLnrange].low = val;
+ GLrange[GLnrange].high = val;
+ }
+ hyphenseen=FALSE;
+ }
+
+ /* Increase the index for ranges found, and protect
+ * against wildly outside array bounds */
+ GLnrange++;
+ if (GLnrange > MaxRange) {
+ GLnrange--;
+ }
+ }
+ GLnrange--;
+
+ /* Now we are going through the low and high values, and check
+ * whether they are in a proper order. Low should be equal or lower
+ * than high. So, go through the loop and swap if needed
+ */
+ for (i=0; i <= GLnrange; i++) {
+ if (GLrange[i].low > GLrange[i].high) {
+ tmp = GLrange[i].low;
+ GLrange[i].low = GLrange[i].high;
+ GLrange[i].high = tmp;
+ }
+ }
+
+ /* In case we want to know what the result ranges are :
+ *
+ * for (i=0; i <= GLnrange; i++) {
+ * printf("L=%u\tH=%u\n",GLrange[i].low,GLrange[i].high);
+ * }
+ *
+ */
+
+ /* End of conv_str_range() */
+ return;
+}
+
+/* This function returns TRUE is the given value is within the range
+ * of the input range entered via (Save/Print As). This is supposed to
+ * be a tiny and quick procedure since this is called for every packet
+ * to be potentially saved.
+ */
+static gboolean packet_is_in_range(guint32 val)
+{
+ guint i;
+
+ for (i=0; i <= GLnrange; i++) {
+ if (val >= GLrange[i].low && val <= GLrange[i].high)
+ return TRUE;
+ }
+ return(FALSE);
+}
+
+static void packet_is_in_range_check(guint32 val)
+{
+ printf("Checking %d\t",val);
+ if (packet_is_in_range(val)) {
+ printf("TRUE\n");
+ } else {
+ printf("FALSE\n");
+ }
+}
+