Rename buffer_ routines to ws_buffer_ to avoid name collisions.
[metze/wireshark/wip.git] / ui / qt / packet_list_record.cpp
1 /* packet_list_record.cpp
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "packet_list_record.h"
23
24 #include <file.h>
25
26 #include <epan/epan_dissect.h>
27 #include <epan/column-info.h>
28 #include <epan/column.h>
29
30 #include "color.h"
31 #include "color_filters.h"
32 #include "frame_tvbuff.h"
33
34 #include <QStringList>
35
36 QMap<int, int> cinfo_column_;
37
38 PacketListRecord::PacketListRecord(frame_data *frameData) :
39     fdata_(frameData),
40 //    columnized_(false),
41     colorized_(false)
42 {
43 }
44
45 QVariant PacketListRecord::columnString(capture_file *cap_file, int column)
46 {
47     // packet_list_store.c:packet_list_get_value
48     g_assert(fdata_);
49
50     if (!cap_file || column < 0 || column > cap_file->cinfo.num_cols) {
51         return QVariant();
52     }
53
54     if (column >= col_text_.size() || col_text_[column].isNull() || !colorized_) {
55         dissect(cap_file, !colorized_);
56     }
57
58     return col_text_.value(column, QByteArray());
59 }
60
61 frame_data *PacketListRecord::frameData() {
62     return fdata_;
63 }
64
65 void PacketListRecord::resetColumns(column_info *cinfo)
66 {
67     if (!cinfo) {
68         return;
69     }
70
71     cinfo_column_.clear();
72     int i, j;
73     for (i = 0, j = 0; i < cinfo->num_cols; i++) {
74         if (!col_based_on_frame_data(cinfo, i)) {
75             cinfo_column_[i] = j;
76             j++;
77         }
78     }
79 }
80
81 void PacketListRecord::dissect(capture_file *cap_file, bool dissect_color)
82 {
83     // packet_list_store.c:packet_list_dissect_and_cache_record
84     epan_dissect_t edt;
85     column_info *cinfo = NULL;
86     gboolean create_proto_tree;
87     struct wtap_pkthdr phdr; /* Packet header */
88     Buffer buf; /* Packet data */
89     gboolean dissect_columns = col_text_.isEmpty();
90
91     if (!cap_file) {
92         return;
93     }
94
95     memset(&phdr, 0, sizeof(struct wtap_pkthdr));
96
97     if (dissect_columns) {
98         cinfo = &cap_file->cinfo;
99     }
100
101     ws_buffer_init(&buf, 1500);
102     if (!cf_read_record_r(cap_file, fdata_, &phdr, &buf)) {
103         /*
104          * Error reading the record.
105          *
106          * Don't set the color filter for now (we might want
107          * to colorize it in some fashion to warn that the
108          * row couldn't be filled in or colorized), and
109          * set the columns to placeholder values, except
110          * for the Info column, where we'll put in an
111          * error message.
112          */
113         if (dissect_columns) {
114             col_fill_in_error(cinfo, fdata_, FALSE, FALSE /* fill_fd_columns */);
115
116             cacheColumnStrings(cinfo);
117         }
118         if (dissect_color) {
119             fdata_->color_filter = NULL;
120             colorized_ = TRUE;
121         }
122         ws_buffer_free(&buf);
123         return;    /* error reading the record */
124     }
125
126     create_proto_tree = (dissect_color && color_filters_used()) ||
127                         (dissect_columns && have_custom_cols(cinfo));
128
129     epan_dissect_init(&edt, cap_file->epan,
130                       create_proto_tree,
131                       FALSE /* proto_tree_visible */);
132
133     if (dissect_color)
134         color_filters_prime_edt(&edt);
135     if (dissect_columns)
136         col_custom_prime_edt(&edt, cinfo);
137
138     /*
139      * XXX - need to catch an OutOfMemoryError exception and
140      * attempt to recover from it.
141      */
142     epan_dissect_run(&edt, cap_file->cd_t, &phdr, frame_tvbuff_new_buffer(fdata_, &buf), fdata_, cinfo);
143
144     if (dissect_color)
145         fdata_->color_filter = color_filters_colorize_packet(&edt);
146
147     if (dissect_columns) {
148         /* "Stringify" non frame_data vals */
149         epan_dissect_fill_in_columns(&edt, FALSE, FALSE /* fill_fd_columns */);
150         cacheColumnStrings(cinfo);
151     }
152
153     if (dissect_color) {
154         colorized_ = true;
155     }
156
157     epan_dissect_cleanup(&edt);
158     ws_buffer_free(&buf);
159 }
160
161 //#define MINIMIZE_STRING_COPYING 1
162 void PacketListRecord::cacheColumnStrings(column_info *cinfo)
163 {
164     // packet_list_store.c:packet_list_change_record(PacketList *packet_list, PacketListRecord *record, gint col, column_info *cinfo)
165     if (!cinfo) {
166         return;
167     }
168
169     col_text_.clear();
170
171     for (int column = 0; column < cinfo->num_cols; ++column) {
172
173 #ifdef MINIMIZE_STRING_COPYING
174         int text_col = cinfo_column_.value(column, -1);
175
176         /* Column based on frame_data or it already contains a value */
177         if (text_col < 0) {
178             col_fill_in_frame_data(fdata_, cinfo, column, FALSE);
179             col_text_.append(cinfo->col_data[column]);
180             continue;
181         }
182
183         switch (cinfo->col_fmt[column]) {
184         case COL_DEF_SRC:
185         case COL_RES_SRC:        /* COL_DEF_SRC is currently just like COL_RES_SRC */
186         case COL_UNRES_SRC:
187         case COL_DEF_DL_SRC:
188         case COL_RES_DL_SRC:
189         case COL_UNRES_DL_SRC:
190         case COL_DEF_NET_SRC:
191         case COL_RES_NET_SRC:
192         case COL_UNRES_NET_SRC:
193         case COL_DEF_DST:
194         case COL_RES_DST:        /* COL_DEF_DST is currently just like COL_RES_DST */
195         case COL_UNRES_DST:
196         case COL_DEF_DL_DST:
197         case COL_RES_DL_DST:
198         case COL_UNRES_DL_DST:
199         case COL_DEF_NET_DST:
200         case COL_RES_NET_DST:
201         case COL_UNRES_NET_DST:
202         case COL_PROTOCOL:
203         case COL_INFO:
204         case COL_IF_DIR:
205         case COL_DCE_CALL:
206         case COL_8021Q_VLAN_ID:
207         case COL_EXPERT:
208         case COL_FREQ_CHAN:
209             if (cinfo->col_data[column] && cinfo->col_data[column] != cinfo->col_buf[column]) {
210                 /* This is a constant string, so we don't have to copy it */
211                 // XXX - ui/gtk/packet_list_store.c uses G_MAXUSHORT. We don't do proper UTF8
212                 // truncation in either case.
213                 int col_text_len = MIN(qstrlen(cinfo->col_data[column]) + 1, COL_MAX_INFO_LEN);
214                 col_text_.append(QByteArray::fromRawData(cinfo->col_data[column], col_text_len));
215                 break;
216             }
217             /* !! FALL-THROUGH!! */
218
219         default:
220             if (!get_column_resolved(column) && cinfo->col_expr.col_expr_val[column]) {
221                 /* Use the unresolved value in col_expr_val */
222                 // XXX Use QContiguousCache?
223                 col_text_.append(cinfo->col_expr.col_expr_val[column]);
224             } else {
225                 col_text_.append(cinfo->col_data[column]);
226             }
227             break;
228         }
229 #else // MINIMIZE_STRING_COPYING
230         // XXX Use QContiguousCache?
231         if (!get_column_resolved(column) && cinfo->col_expr.col_expr_val[column]) {
232             /* Use the unresolved value in col_expr_val */
233             col_text_.append(cinfo->col_expr.col_expr_val[column]);
234         } else {
235             int text_col = cinfo_column_.value(column, -1);
236
237             if (text_col < 0) {
238                 col_fill_in_frame_data(fdata_, cinfo, column, FALSE);
239             }
240             col_text_.append(cinfo->col_data[column]);
241         }
242 #endif // MINIMIZE_STRING_COPYING
243     }
244 }
245
246 /*
247  * Editor modelines
248  *
249  * Local Variables:
250  * c-basic-offset: 4
251  * tab-width: 8
252  * indent-tabs-mode: nil
253  * End:
254  *
255  * ex: set shiftwidth=4 tabstop=8 expandtab:
256  * :indentSize=4:tabSize=8:noTabs=true:
257  */