2 * Packet range routines (save, print, ...)
6 * Dick Gooris <gooris@lucent.com>
7 * Ulf Lamping <ulf.lamping@web.de>
9 * Ethereal - Network traffic analyzer
10 * By Gerald Combs <gerald@ethereal.com>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
37 #include <epan/frame_data.h>
45 static gboolean packet_is_in_range(packet_range_t *range, guint32 val);
48 /* (re-)calculate the packet counts (except the user specified range) */
49 void packet_range_calc(packet_range_t *range) {
50 guint32 current_count;
53 guint32 displayed_mark_low;
54 guint32 displayed_mark_high;
58 range->selected_packet = 0L;
62 range->mark_range_cnt = 0L;
64 displayed_mark_low = 0L;
65 displayed_mark_high = 0L;
66 range->displayed_cnt = 0L;
67 range->displayed_marked_cnt = 0L;
68 range->displayed_mark_range_cnt=0L;
70 /* The next for-loop is used to obtain the amount of packets to be processed
71 * and is used to present the information in the Save/Print As widget.
72 * We have different types of ranges: All the packets, the number
73 * of packets of a marked range, a single packet, and a user specified
74 * packet range. The last one is not calculated here since this
75 * data must be entered in the widget by the user.
79 for(packet = cfile.plist; packet != NULL; packet = packet->next) {
81 if (cfile.current_frame == packet) {
82 range->selected_packet = current_count;
84 if (packet->flags.passed_dfilter) {
85 range->displayed_cnt++;
87 if (packet->flags.marked) {
88 if (packet->flags.passed_dfilter) {
89 range->displayed_marked_cnt++;
90 if (displayed_mark_low == 0) {
91 displayed_mark_low = current_count;
93 if (current_count > displayed_mark_high) {
94 displayed_mark_high = current_count;
99 mark_low = current_count;
101 if (current_count > mark_high) {
102 mark_high = current_count;
108 for(packet = cfile.plist; packet != NULL; packet = packet->next) {
111 if (current_count >= mark_low &&
112 current_count <= mark_high)
114 range->mark_range_cnt++;
117 if (current_count >= displayed_mark_low &&
118 current_count <= displayed_mark_high)
120 if (packet->flags.passed_dfilter) {
121 range->displayed_mark_range_cnt++;
126 /* in case we marked just one packet, we add 1. */
127 /*if (cfile.marked_count != 0) {
128 range->mark_range = mark_high - mark_low + 1;
131 /* in case we marked just one packet, we add 1. */
132 /*if (range->displayed_marked_cnt != 0) {
133 range->displayed_mark_range = displayed_mark_high - displayed_mark_low + 1;
138 /* (re-)calculate the user specified packet range counts */
139 void packet_range_calc_user(packet_range_t *range) {
140 guint32 current_count;
143 range->user_range_cnt = 0L;
144 range->displayed_user_range_cnt = 0L;
147 for(packet = cfile.plist; packet != NULL; packet = packet->next) {
150 if (packet_is_in_range(range, current_count)) {
151 range->user_range_cnt++;
152 if (packet->flags.passed_dfilter) {
153 range->displayed_user_range_cnt++;
160 /* init the range struct */
161 void packet_range_init(packet_range_t *range) {
163 range->process = range_process_all;
164 range->process_filtered = FALSE;
166 range->ranges[range->nranges].low = 0L;
167 range->ranges[range->nranges].high = 0L;
169 /* calculate all packet range counters */
170 packet_range_calc(range);
171 packet_range_calc_user(range);
174 /* init the processing run */
175 void packet_range_process_init(packet_range_t *range) {
176 /* "enumeration" values */
177 range->marked_range_active = FALSE;
178 range->selected_done = FALSE;
180 if (range->process_filtered == FALSE) {
181 range->marked_range_left = range->mark_range_cnt;
183 range->marked_range_left = range->displayed_mark_range_cnt;
187 /* do we have to process all packets? */
188 gboolean packet_range_process_all(packet_range_t *range) {
189 return range->process == range_process_all && !range->process_filtered;
192 /* do we have to process this packet? */
193 range_process_e packet_range_process_packet(packet_range_t *range, frame_data *fdata) {
195 switch(range->process) {
196 case(range_process_all):
198 case(range_process_selected):
199 if (range->selected_done) {
200 return range_processing_finished;
202 if (fdata->num != cfile.current_frame->num) {
203 return range_process_next;
205 range->selected_done = TRUE;
207 case(range_process_marked):
208 if (fdata->flags.marked == FALSE) {
209 return range_process_next;
212 case(range_process_marked_range):
213 if (range->marked_range_left == 0) {
214 return range_processing_finished;
216 if (fdata->flags.marked == TRUE) {
217 range->marked_range_active = TRUE;
219 if (range->marked_range_active == FALSE ) {
220 return range_process_next;
222 if (!range->process_filtered ||
223 (range->process_filtered && fdata->flags.passed_dfilter == TRUE))
225 range->marked_range_left--;
228 case(range_process_user_range):
229 if (packet_is_in_range(range, fdata->num) == FALSE) {
230 return range_process_next;
234 g_assert_not_reached();
237 /* this packet has to pass the display filter but didn't? -> try next */
238 if (range->process_filtered && fdata->flags.passed_dfilter == FALSE) {
239 return range_process_next;
242 /* We fell through the conditions above, so we accept this packet */
243 return range_process_this;
247 /******************** Range Entry Parser *********************************/
249 /* Converts a range string to a fast comparable array of ranges.
250 * The parameter 'es' points to the string to be converted, and is defined in
251 * the Save/Print-As widget.
253 * This function fills the array ranges containing low and high values indexed
254 * by a global variable nranges. After having called this function, the function
255 * packet_is_in_range() determines whether a given (packet) number is within
258 * In case of a single packet number, we make a range where low is equal to high.
259 * We strip any characters other than commas, digits, or hyphens. We take care
260 * on wrongly entered ranges; opposite order will be taken care of.
262 * The following syntax is accepted :
264 * 1-20,30-40 Range from 1 to 20, and packets 30 to 40
265 * -20,30 Range from 1 to 20, and packet 30
266 * 20,30,40- Packet number 20, 30, and the range from 40 to the end
267 * 20-10,30-25 Range from 10 to 20, and from 25 to 30
271 void packet_range_convert_str(packet_range_t *range, const gchar *es)
273 gchar EntryStr[255], OrgStr[255], value[255], p;
278 /* Reset the number of ranges we are going to find */
280 range->ranges[range->nranges].low = 0L;
281 range->ranges[range->nranges].high = 0L;
283 /* Make a copy of the string, and check the validity of the input */
285 if (strlen(OrgStr) == 0 ) {
289 /* Only keep digits, commas, and hyphens. */
290 for (i=0; i<=strlen(OrgStr); i++) {
291 if ( isdigit((guchar)OrgStr[i]) || OrgStr[i] == '-' || OrgStr[i] == ',' ) {
292 EntryStr[j++] = OrgStr[i];
297 /* Remove any starting commas */
298 strcpy(OrgStr,EntryStr);
300 while (OrgStr[i] == ',') {
303 strcpy(EntryStr,OrgStr+i);
305 /* Remove any double commas */
306 strcpy(OrgStr,EntryStr);
309 for (i=0; i<=strlen(OrgStr); i++) {
310 if ( OrgStr[i] != ',' || p != ',') {
311 EntryStr[j++] = OrgStr[i];
317 /* Remove any double hyphens */
318 strcpy(OrgStr,EntryStr);
321 for (i=0; i<=strlen(OrgStr); i++) {
322 if (OrgStr[i] != '-' || p != '-' || i == 0) {
323 EntryStr[j++] = OrgStr[i];
329 /* Remove any trailing commas */
330 i = strlen(EntryStr) - 1;
331 while (EntryStr[i] == ',') {
336 /* The entry string is now filtered, and ready for further parsing */
337 /* printf("Function : packet_range_convert_str EntryStr = %s\n",EntryStr); */
339 /* Now we are going to process the ranges separately until we get a comma,
342 * We build a structure array called ranges of high and low values. After the
343 * following loop, we have the nranges variable which tells how many ranges
344 * were found. The number of individual ranges is limited to 'MaxRanges'
349 for (i=0; i<=strlen(EntryStr);i++) {
351 /* Copy the digit string until a no-digit character is seen */
352 if (isdigit((guchar)EntryStr[i])) {
353 value[j++] = EntryStr[i];
357 /* Terminate the digit string, and convert it */
362 /* In case we see a hyphen, store the value we read in the low part
363 * of ranges. In case it is a trailer hyphen, store the low value, and
364 * set the high value to the maximum of packets captured.
366 if (EntryStr[i] == '-') {
367 /* If this is a trailer hyphen, then treat it in a different
368 * way, then the high value is the maximum number of packets counted
371 if (i == strlen(EntryStr)-1) {
372 range->ranges[range->nranges].low = val;
373 range->ranges[range->nranges].high = cfile.count;
377 /* Store the low value of the range */
378 range->ranges[range->nranges].low = val;
384 /* In case we see a comma, or end of string */
385 if (EntryStr[i] == ',' || i == strlen(EntryStr)) {
387 /* Normal treatment: store the high value range in ranges */
388 range->ranges[range->nranges].high = val;
390 /* We did not see a hyphen and we get a comma, then this must
391 * be a single packet number */
392 range->ranges[range->nranges].low = val;
393 range->ranges[range->nranges].high = val;
398 /* Increase the index for the number of ranges we found, and protect
399 * against wildly outside array bound jumps */
401 if (range->nranges > MaxRange) {
407 /* Now we are going through the low and high values, and check
408 * whether they are in a proper order. Low should be equal or lower
409 * than high. So, go through the loop and swap if needed.
411 for (i=0; i <= range->nranges; i++) {
412 if (range->ranges[i].low > range->ranges[i].high) {
413 tmp = range->ranges[i].low;
414 range->ranges[i].low = range->ranges[i].high;
415 range->ranges[i].high = tmp;
419 /* In case we want to know what the result ranges are :
421 * for (i=0; i <= nranges; i++) {
422 * printf("Function : packet_range_convert_str L=%u \t H=%u\n",ranges[i].low,ranges[i].high);
427 /* calculate new user specified packet range counts */
428 packet_range_calc_user(range);
429 } /* packet_range_convert_str */
431 /* This function returns TRUE if a given value is within one of the ranges
432 * stored in the ranges array.
434 static gboolean packet_is_in_range(packet_range_t *range, guint32 val)
438 for (i=0; i <= range->nranges; i++) {
439 if (val >= range->ranges[i].low && val <= range->ranges[i].high)
446 /* This is a debug function to check the range functionality */
447 static void packet_is_in_range_check(packet_range_t *range, guint32 val)
450 /* Print the result for a given value */
451 printf("Function : packet_is_in_range_check Number %u\t",val);
453 if (packet_is_in_range(range, val)) {
454 printf("is in range\n");
456 printf("is not in range\n");