From 0772dd06b4f7395cceb3daee19de97f34e83b08f Mon Sep 17 00:00:00 2001 From: Anders Broman Date: Fri, 11 Sep 2009 11:58:00 +0000 Subject: New_packet_list Select the correct frame in packet details when filtering. svn path=/trunk/; revision=29857 --- file.c | 344 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 316 insertions(+), 28 deletions(-) (limited to 'file.c') diff --git a/file.c b/file.c index 3a2bd9d2c4..e206d564b5 100644 --- a/file.c +++ b/file.c @@ -1667,8 +1667,11 @@ cf_redissect_packets(capture_file *cf) any state information they have (because a preference that affects some dissector has changed, meaning some dissector might construct its state differently from the way it was constructed the last time). */ + +/* Rescan packets with "old" packet list */ +#ifndef NEW_PACKET_LIST static void -rescan_packets(capture_file *cf, const char *action, const char *action_item, +rescan_packets_old(capture_file *cf, const char *action, const char *action_item, gboolean refilter, gboolean redissect) { frame_data *fdata; @@ -1689,11 +1692,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, dfilter_t *dfcode; gboolean filtering_tap_listeners; guint tap_flags; -#ifdef NEW_PACKET_LIST - gboolean add_to_packet_list = FALSE; -#else gboolean add_to_packet_list = TRUE; -#endif /* Compile the current display filter. * We assume this will not fail since cf->dfilter is only set in @@ -1724,14 +1723,10 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, /* Freeze the packet list while we redo it, so we don't get any screen updates while it happens. */ -#ifdef NEW_PACKET_LIST - new_packet_list_freeze(); -#else packet_list_freeze(); /* Clear it out. */ packet_list_clear(); -#endif if (redissect) { /* We need to re-initialize all the state information that protocols @@ -1748,12 +1743,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, /* Initialize all data structures used for dissection. */ init_dissection(); -#ifdef NEW_PACKET_LIST - /* We need to redissect the packets so we have to discard our old - * packet list store. */ - new_packet_list_clear(); - add_to_packet_list = TRUE; -#endif } /* We don't yet know which will be the first and last frames displayed. */ @@ -1898,11 +1887,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, /* We are done redissecting the packet list. */ cf->redissecting = FALSE; -#ifndef NEW_PACKET_LIST - /* Re-sort the list using the previously selected order */ - packet_list_set_sort_column(); -#endif - if (redissect) { /* Clear out what remains of the visited flags and per-frame data pointers. @@ -1928,13 +1912,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, destroy_progress_dlg(progbar); /* Unfreeze the packet list. */ -#ifdef NEW_PACKET_LIST - if (!add_to_packet_list) - new_packet_list_recreate_visible_rows(); - new_packet_list_thaw(); -#else packet_list_thaw(); -#endif if (selected_row == -1) { /* The selected frame didn't pass the filter. */ @@ -1973,7 +1951,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, /* There are no frames displayed at all. */ cf_unselect_packet(cf); } else { -#ifndef NEW_PACKET_LIST /* Either the frame that was selected passed the filter, or we've found the nearest displayed frame to that frame. Select it, make it the focus row, and make it visible. */ @@ -1982,7 +1959,6 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, cf->current_row = -1; } packet_list_set_selected_row(selected_row); -#endif /* NEW_PACKET_LIST */ } /* Cleanup and release all dfilter resources */ @@ -1990,6 +1966,318 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, dfilter_free(dfcode); } } +#endif /* NEW_PACKET_LIST rescan_packets_old*/ + +static void +rescan_packets(capture_file *cf, const char *action, const char *action_item, + gboolean refilter, gboolean redissect) +{ +#ifndef NEW_PACKET_LIST + rescan_packets_old(cf, action, action_item, refilter, redissect); +} +#else + /* Rescan packets new packet list */ + frame_data *fdata; + progdlg_t *progbar = NULL; + gboolean stop_flag; + int count; + int err; + gchar *err_info; + frame_data *selected_frame, *preceding_frame, *following_frame, *prev_frame; + int selected_frame_num, preceding_frame_num, following_frame_num, prev_frame_num; + gboolean selected_frame_seen; + int frame_num; + float progbar_val; + GTimeVal start_time; + gchar status_str[100]; + int progbar_nextstep; + int progbar_quantum; + dfilter_t *dfcode; + gboolean filtering_tap_listeners; + guint tap_flags; + gboolean add_to_packet_list = FALSE; + + /* Compile the current display filter. + * We assume this will not fail since cf->dfilter is only set in + * cf_filter IFF the filter was valid. + */ + dfcode=NULL; + if(cf->dfilter){ + dfilter_compile(cf->dfilter, &dfcode); + } + + /* Do we have any tap listeners with filters? */ + filtering_tap_listeners = have_filtering_tap_listeners(); + + /* Get the union of the flags for all tap listeners. */ + tap_flags = union_of_tap_listener_flags(); + + cum_bytes=0; + reset_tap_listeners(); + /* Which frame, if any, is the currently selected frame? + XXX - should the selected frame or the focus frame be the "current" + frame, that frame being the one from which "Find Frame" searches + start? */ + selected_frame = cf->current_frame; + + /* Mark frane num as not found */ + selected_frame_num = -1; + + /* Freeze the packet list while we redo it, so we don't get any + screen updates while it happens. */ + new_packet_list_freeze(); + + if (redissect) { + /* We need to re-initialize all the state information that protocols + keep, because some preference that controls a dissector has changed, + which might cause the state information to be constructed differently + by that dissector. */ + + /* We might receive new packets while redissecting, and we don't + want to dissect those before their time. */ + cf->redissecting = TRUE; + + /* Cleanup all data structures used for dissection. */ + cleanup_dissection(); + /* Initialize all data structures used for dissection. */ + init_dissection(); + + /* We need to redissect the packets so we have to discard our old + * packet list store. */ + new_packet_list_clear(); + add_to_packet_list = TRUE; + } + + /* We don't yet know which will be the first and last frames displayed. */ + cf->first_displayed = NULL; + cf->last_displayed = NULL; + + reset_elapsed(); + + /* We currently don't display any packets */ + cf->displayed_count = 0; + + /* Iterate through the list of frames. Call a routine for each frame + to check whether it should be displayed and, if so, add it to + the display list. */ + nstime_set_unset(&first_ts); + nstime_set_unset(&prev_dis_ts); + + /* Update the progress bar when it gets to this value. */ + progbar_nextstep = 0; + /* When we reach the value that triggers a progress bar update, + bump that value by this amount. */ + progbar_quantum = cf->count/N_PROGBAR_UPDATES; + /* Count of packets at which we've looked. */ + count = 0; + /* Progress so far. */ + progbar_val = 0.0f; + + stop_flag = FALSE; + g_get_current_time(&start_time); + + /* no previous row yet */ + frame_num = -1; + prev_frame_num = -1; + prev_frame = NULL; + + preceding_frame_num = -1; + preceding_frame = NULL; + following_frame_num = -1; + following_frame = NULL; + + selected_frame_seen = FALSE; + + for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) { + /* Create the progress bar if necessary. + We check on every iteration of the loop, so that it takes no + longer than the standard time to create it (otherwise, for a + large file, we might take considerably longer than that standard + time in order to get to the next progress bar step). */ + if (progbar == NULL) + progbar = delayed_create_progress_dlg(action, action_item, TRUE, + &stop_flag, &start_time, + progbar_val); + + /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; + when we update it, we have to run the GTK+ main loop to get it + to repaint what's pending, and doing so may involve an "ioctl()" + to see if there's any pending input from an X server, and doing + that for every packet can be costly, especially on a big file. */ + if (count >= progbar_nextstep) { + /* let's not divide by zero. I should never be started + * with count == 0, so let's assert that + */ + g_assert(cf->count > 0); + progbar_val = (gfloat) count / cf->count; + + if (progbar != NULL) { + g_snprintf(status_str, sizeof(status_str), + "%4u of %u frames", count, cf->count); + update_progress_dlg(progbar, progbar_val, status_str); + } + + progbar_nextstep += progbar_quantum; + } + + if (stop_flag) { + /* Well, the user decided to abort the filtering. Just stop. + + XXX - go back to the previous filter? Users probably just + want not to wait for a filtering operation to finish; + unless we cancel by having no filter, reverting to the + previous filter will probably be even more expensive than + continuing the filtering, as it involves going back to the + beginning and filtering, and even with no filter we currently + have to re-generate the entire clist, which is also expensive. + + I'm not sure what Network Monitor does, but it doesn't appear + to give you an unfiltered display if you cancel. */ + break; + } + + count++; + + if (redissect) { + /* Since all state for the frame was destroyed, mark the frame + * as not visited, free the GSList referring to the state + * data (the per-frame data itself was freed by + * "init_dissection()"), and null out the GSList pointer. */ + fdata->flags.visited = 0; + if (fdata->pfd) { + g_slist_free(fdata->pfd); + fdata->pfd = NULL; + } + } + + if (!wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header, + cf->pd, fdata->cap_len, &err, &err_info)) { + simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, + cf_read_error_message(err, err_info), cf->filename); + break; + } + + /* If the previous frame is displayed, and we haven't yet seen the + selected frame, remember that frame - it's the closest one we've + yet seen before the selected frame. */ + if (prev_frame_num != -1 && !selected_frame_seen && prev_frame->flags.passed_dfilter) { + preceding_frame_num = prev_frame_num; + preceding_frame = prev_frame; + } + add_packet_to_packet_list(fdata, cf, dfcode, filtering_tap_listeners, + tap_flags, &cf->pseudo_header, cf->pd, + refilter, + add_to_packet_list); + + /* If this frame is displayed, and this is the first frame we've + seen displayed after the selected frame, remember this frame - + it's the closest one we've yet seen at or after the selected + frame. */ + if (fdata->flags.passed_dfilter && selected_frame_seen && following_frame_num == -1) { + following_frame_num = fdata->num; + following_frame = fdata; + } + if (fdata == selected_frame) { + selected_frame_seen = TRUE; + if (fdata->flags.passed_dfilter) + selected_frame_num = fdata->num; + } + + /* Remember this frame - it'll be the previous frame + on the next pass through the loop. */ + prev_frame_num = fdata->num; + prev_frame = fdata; + } + + /* We are done redissecting the packet list. */ + cf->redissecting = FALSE; + + if (redissect) { + /* Clear out what remains of the visited flags and per-frame data + pointers. + + XXX - that may cause various forms of bogosity when dissecting + these frames, as they won't have been seen by this sequential + pass, but the only alternative I see is to keep scanning them + even though the user requested that the scan stop, and that + would leave the user stuck with an Wireshark grinding on + until it finishes. Should we just stick them with that? */ + for (; fdata != NULL; fdata = fdata->next) { + fdata->flags.visited = 0; + if (fdata->pfd) { + g_slist_free(fdata->pfd); + fdata->pfd = NULL; + } + } + } + + /* We're done filtering the packets; destroy the progress bar if it + was created. */ + if (progbar != NULL) + destroy_progress_dlg(progbar); + + /* Unfreeze the packet list. */ + if (!add_to_packet_list) + new_packet_list_recreate_visible_rows(); + + new_packet_list_thaw(); + + if (selected_frame_num == -1) { + /* The selected frame didn't pass the filter. */ + if (selected_frame == NULL) { + /* That's because there *was* no selected frame. Make the first + displayed frame the current frame. */ + selected_frame_num = 0; + } else { + /* Find the nearest displayed frame to the selected frame (whether + it's before or after that frame) and make that the current frame. + If the next and previous displayed frames are equidistant from the + selected frame, choose the next one. */ + g_assert(following_frame == NULL || + following_frame->num >= selected_frame->num); + g_assert(preceding_frame == NULL || + preceding_frame->num <= selected_frame->num); + if (following_frame == NULL) { + /* No frame after the selected frame passed the filter, so we + have to select the last displayed frame before the selected + frame. */ + selected_frame_num = preceding_frame_num; + selected_frame = preceding_frame; + } else if (preceding_frame == NULL) { + /* No frame before the selected frame passed the filter, so we + have to select the first displayed frame after the selected + frame. */ + selected_frame_num = following_frame_num; + selected_frame = following_frame; + } else { + /* Frames before and after the selected frame passed the filter, so + we'll select the previous frame */ + selected_frame_num = preceding_frame_num; + selected_frame = preceding_frame; + } + } + } + + if (selected_frame_num == -1) { + /* There are no frames displayed at all. */ + cf_unselect_packet(cf); + } else { + /* Either the frame that was selected passed the filter, or we've + found the nearest displayed frame to that frame. Select it, make + it the focus row, and make it visible. */ + if (selected_frame_num == 0) { + new_packet_list_select_first_row(); + }else{ + new_packet_list_find_row_from_data(selected_frame, TRUE); + } + } + + /* Cleanup and release all dfilter resources */ + if (dfcode != NULL){ + dfilter_free(dfcode); + } +} +#endif /* NEW_PACKET_LIST */ /* * Scan trough all frame data and recalculate the ref time * without rereading the file. -- cgit v1.2.3