MSWSP: fix dissect_mswsp_smb()
[wireshark-wip.git] / epan / dissectors / packet-jpeg.c
blobbe87693edb579aaaf88e59c067ac48594f95d928
1 /* packet-jpeg.c
3 * Routines for RFC 2435 JPEG dissection
5 * $Id$
7 * Copyright 2006
8 * Erwin Rol <erwin@erwinrol.com>
9 * Copyright 2001,
10 * Francisco Javier Cabello Torres, <fjcabello@vtools.es>
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #define NEW_PROTO_TREE_API
33 #include "config.h"
35 #include <glib.h>
36 #include <epan/packet.h>
38 #include <epan/rtp_pt.h>
40 #include "packet-ber.h"
42 static dissector_handle_t jpeg_handle;
44 static header_field_info *hfi_jpeg = NULL;
46 #define JPEG_HFI_INIT HFI_INIT(proto_jpeg)
48 /* JPEG header fields */
49 static header_field_info hfi_rtp_jpeg_main_hdr JPEG_HFI_INIT = {
50 "Main Header",
51 "jpeg.main_hdr",
52 FT_NONE, BASE_NONE, NULL, 0,
53 NULL, HFILL
56 static header_field_info hfi_rtp_jpeg_main_hdr_ts JPEG_HFI_INIT = {
57 "Type Specific",
58 "jpeg.main_hdr.ts",
59 FT_UINT8, BASE_DEC, NULL, 0,
60 NULL, HFILL
63 static header_field_info hfi_rtp_jpeg_main_hdr_offs JPEG_HFI_INIT = {
64 "Fragment Offset",
65 "jpeg.main_hdr.offset",
66 FT_UINT24, BASE_DEC, NULL, 0,
67 NULL, HFILL
70 static header_field_info hfi_rtp_jpeg_main_hdr_type JPEG_HFI_INIT = {
71 "Type",
72 "jpeg.main_hdr.type",
73 FT_UINT8, BASE_DEC, NULL, 0,
74 NULL, HFILL
77 static header_field_info hfi_rtp_jpeg_main_hdr_q JPEG_HFI_INIT = {
78 "Q",
79 "jpeg.main_hdr.q",
80 FT_UINT8, BASE_DEC, NULL, 0,
81 NULL, HFILL
84 static header_field_info hfi_rtp_jpeg_main_hdr_width JPEG_HFI_INIT = {
85 "Width",
86 "jpeg.main_hdr.width",
87 FT_UINT8, BASE_DEC, NULL, 0,
88 NULL, HFILL
91 static header_field_info hfi_rtp_jpeg_main_hdr_height JPEG_HFI_INIT = {
92 "Height",
93 "jpeg.main_hdr.height",
94 FT_UINT8, BASE_DEC, NULL, 0,
95 NULL, HFILL
98 static header_field_info hfi_rtp_jpeg_restart_hdr JPEG_HFI_INIT = {
99 "Restart Marker Header",
100 "jpeg.restart_hdr",
101 FT_NONE, BASE_NONE, NULL, 0,
102 NULL, HFILL
105 static header_field_info hfi_rtp_jpeg_restart_hdr_interval JPEG_HFI_INIT = {
106 "Restart Interval",
107 "jpeg.restart_hdr.interval",
108 FT_UINT16, BASE_DEC, NULL, 0,
109 NULL, HFILL
112 static header_field_info hfi_rtp_jpeg_restart_hdr_f JPEG_HFI_INIT = {
113 "F",
114 "jpeg.restart_hdr.f",
115 FT_UINT16, BASE_DEC, NULL, 0x8000,
116 NULL, HFILL
119 static header_field_info hfi_rtp_jpeg_restart_hdr_l JPEG_HFI_INIT = {
120 "L",
121 "jpeg.restart_hdr.l",
122 FT_UINT16, BASE_DEC, NULL, 0x4000,
123 NULL, HFILL
126 static header_field_info hfi_rtp_jpeg_restart_hdr_count JPEG_HFI_INIT = {
127 "Restart Count",
128 "jpeg.restart_hdr.count",
129 FT_UINT16, BASE_DEC, NULL, 0x3FFF,
130 NULL, HFILL
133 static header_field_info hfi_rtp_jpeg_qtable_hdr JPEG_HFI_INIT = {
134 "Quantization Table Header",
135 "jpeg.qtable_hdr",
136 FT_NONE, BASE_NONE, NULL, 0,
137 NULL, HFILL
140 static header_field_info hfi_rtp_jpeg_qtable_hdr_mbz JPEG_HFI_INIT = {
141 "MBZ",
142 "jpeg.qtable_hdr.mbz",
143 FT_UINT8, BASE_DEC, NULL, 0,
144 NULL, HFILL
147 static header_field_info hfi_rtp_jpeg_qtable_hdr_prec JPEG_HFI_INIT = {
148 "Precision",
149 "jpeg.qtable_hdr.precision",
150 FT_UINT8, BASE_DEC, NULL, 0,
151 NULL, HFILL
154 static header_field_info hfi_rtp_jpeg_qtable_hdr_length JPEG_HFI_INIT = {
155 "Length",
156 "jpeg.qtable_hdr.length",
157 FT_UINT16, BASE_DEC, NULL, 0,
158 NULL, HFILL
161 static header_field_info hfi_rtp_jpeg_qtable_hdr_data JPEG_HFI_INIT = {
162 "Quantization Table Data",
163 "jpeg.qtable_hdr.data",
164 FT_BYTES, BASE_NONE, NULL, 0,
165 NULL, HFILL
169 static header_field_info hfi_rtp_jpeg_payload JPEG_HFI_INIT = {
170 "Payload",
171 "jpeg.payload",
172 FT_BYTES, BASE_NONE, NULL, 0,
173 NULL, HFILL
177 /* JPEG fields defining a sub tree */
178 static gint ett_jpeg = -1;
180 static void
181 dissect_jpeg( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
183 proto_item *ti = NULL;
184 proto_tree *jpeg_tree = NULL;
185 proto_tree *main_hdr_tree = NULL;
186 proto_tree *restart_hdr_tree = NULL;
187 proto_tree *qtable_hdr_tree = NULL;
188 guint32 fragment_offset = 0;
189 guint16 len = 0;
190 guint8 type = 0;
191 guint8 q = 0;
192 gint h = 0;
193 gint w = 0;
195 unsigned int offset = 0;
197 col_set_str(pinfo->cinfo, COL_PROTOCOL, "JPEG");
199 col_set_str(pinfo->cinfo, COL_INFO, "JPEG message");
201 if ( tree ) {
202 ti = proto_tree_add_item( tree, hfi_jpeg, tvb, offset, -1, ENC_NA );
203 jpeg_tree = proto_item_add_subtree( ti, ett_jpeg );
205 ti = proto_tree_add_item(jpeg_tree, &hfi_rtp_jpeg_main_hdr, tvb, offset, 8, ENC_NA);
206 main_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
208 proto_tree_add_item(main_hdr_tree, &hfi_rtp_jpeg_main_hdr_ts, tvb, offset, 1, ENC_BIG_ENDIAN);
209 offset += 1;
210 proto_tree_add_item(main_hdr_tree, &hfi_rtp_jpeg_main_hdr_offs, tvb, offset, 3, ENC_BIG_ENDIAN);
211 fragment_offset = tvb_get_ntoh24(tvb, offset);
212 offset += 3;
213 proto_tree_add_item(main_hdr_tree, &hfi_rtp_jpeg_main_hdr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
214 type = tvb_get_guint8(tvb, offset);
215 offset += 1;
216 proto_tree_add_item(main_hdr_tree, &hfi_rtp_jpeg_main_hdr_q, tvb, offset, 1, ENC_BIG_ENDIAN);
217 q = tvb_get_guint8(tvb, offset);
218 offset += 1;
219 w = tvb_get_guint8(tvb, offset) * 8;
220 proto_tree_add_uint(main_hdr_tree, &hfi_rtp_jpeg_main_hdr_width, tvb, offset, 1, w);
221 offset += 1;
222 h = tvb_get_guint8(tvb, offset) * 8;
223 proto_tree_add_uint(main_hdr_tree, &hfi_rtp_jpeg_main_hdr_height, tvb, offset, 1, h);
224 offset += 1;
226 if (type >= 64 && type <= 127) {
227 ti = proto_tree_add_item(jpeg_tree, &hfi_rtp_jpeg_restart_hdr, tvb, offset, 4, ENC_NA);
228 restart_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
229 proto_tree_add_item(restart_hdr_tree, &hfi_rtp_jpeg_restart_hdr_interval, tvb, offset, 2, ENC_BIG_ENDIAN);
230 offset += 2;
231 proto_tree_add_item(restart_hdr_tree, &hfi_rtp_jpeg_restart_hdr_f, tvb, offset, 2, ENC_BIG_ENDIAN);
232 proto_tree_add_item(restart_hdr_tree, &hfi_rtp_jpeg_restart_hdr_l, tvb, offset, 2, ENC_BIG_ENDIAN);
233 proto_tree_add_item(restart_hdr_tree, &hfi_rtp_jpeg_restart_hdr_count, tvb, offset, 2, ENC_BIG_ENDIAN);
234 offset += 2;
237 if (q >= 128 && fragment_offset == 0) {
238 ti = proto_tree_add_item(jpeg_tree, &hfi_rtp_jpeg_qtable_hdr, tvb, offset, -1, ENC_NA);
239 qtable_hdr_tree = proto_item_add_subtree(ti, ett_jpeg);
240 proto_tree_add_item(qtable_hdr_tree, &hfi_rtp_jpeg_qtable_hdr_mbz, tvb, offset, 1, ENC_BIG_ENDIAN);
241 offset += 1;
242 proto_tree_add_item(qtable_hdr_tree, &hfi_rtp_jpeg_qtable_hdr_prec, tvb, offset, 1, ENC_BIG_ENDIAN);
243 offset += 1;
244 proto_tree_add_item(qtable_hdr_tree, &hfi_rtp_jpeg_qtable_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
245 len = tvb_get_ntohs(tvb, offset);
246 offset += 2;
247 if (len > 0) {
248 proto_tree_add_item(qtable_hdr_tree, &hfi_rtp_jpeg_qtable_hdr_data, tvb, offset, len, ENC_NA);
249 offset += len;
251 proto_item_set_len(ti, len + 4);
254 /* The rest of the packet is the JPEG data */
255 proto_tree_add_item( jpeg_tree, &hfi_rtp_jpeg_payload, tvb, offset, -1, ENC_NA );
259 void
260 proto_register_jpeg(void)
262 #ifndef HAVE_HFI_SECTION_INIT
263 static header_field_info *hfi[] =
265 &hfi_rtp_jpeg_main_hdr,
266 &hfi_rtp_jpeg_main_hdr_ts,
267 &hfi_rtp_jpeg_main_hdr_offs,
268 &hfi_rtp_jpeg_main_hdr_type,
269 &hfi_rtp_jpeg_main_hdr_q,
270 &hfi_rtp_jpeg_main_hdr_width,
271 &hfi_rtp_jpeg_main_hdr_height,
272 &hfi_rtp_jpeg_restart_hdr,
273 &hfi_rtp_jpeg_restart_hdr_interval,
274 &hfi_rtp_jpeg_restart_hdr_f,
275 &hfi_rtp_jpeg_restart_hdr_l,
276 &hfi_rtp_jpeg_restart_hdr_count,
277 &hfi_rtp_jpeg_qtable_hdr,
278 &hfi_rtp_jpeg_qtable_hdr_mbz,
279 &hfi_rtp_jpeg_qtable_hdr_prec,
280 &hfi_rtp_jpeg_qtable_hdr_length,
281 &hfi_rtp_jpeg_qtable_hdr_data,
282 &hfi_rtp_jpeg_payload,
284 #endif
286 static gint *ett[] =
288 &ett_jpeg,
291 int proto_jpeg;
293 proto_jpeg = proto_register_protocol("RFC 2435 JPEG","JPEG","jpeg");
294 hfi_jpeg = proto_registrar_get_nth(proto_jpeg);
296 proto_register_fields(proto_jpeg, hfi, array_length(hfi));
297 proto_register_subtree_array(ett, array_length(ett));
299 jpeg_handle = create_dissector_handle(dissect_jpeg, proto_jpeg);
301 /* RFC 2798 */
302 register_ber_oid_dissector_handle("0.9.2342.19200300.100.1.60", jpeg_handle, proto_jpeg, "jpegPhoto");
305 void
306 proto_reg_handoff_jpeg(void)
308 dissector_add_uint("rtp.pt", PT_JPEG, jpeg_handle);