1 /* packet-mrcpv2.c
2 * Routines for Media Resource Control Protocol Version 2 (MRCPv2) dissection
3 * Copyright 2012, Zeljko Ancimer <zancimer[AT]gmail.com>
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11 /*
12 * Based on RFC 6787
13 *
14 * TODO:
15 * - TLS has not been tested
16 * - MRCP conversation (similar to VoIP Calls)
17 * - convert header value into the correct types (numbers, booleans,...);
18 * currently all values are treated as strings so one has to be
19 * careful with the usage of filters; to do this, one has to go through
20 * the mrcp draft and look for the definition of each header (see
21 * chapter titled "15. ABNF Normative Definition")
22 */
23 #include "config.h"
24
25 /* Include only as needed */
26 #include <stdlib.h>
27
28 #include <epan/packet.h>
29 #include <epan/expert.h>
30 #include "packet-tcp.h"
31
32 #include <wsutil/str_util.h>
33 #include <wsutil/strtoi.h>
34
35 void proto_register_mrcpv2(void);
36 void proto_reg_handoff_mrcpv2(void);
37
38 /* mrcp-version SP message-length */
39 /* mrcp-version = "MRCP" "/" 1*2DIGIT "." 1*2DIGIT ==> up to 10 chars */
40 /* SP ==> whitespace, 1 char */
41 /* message-length = 1*19DIGIT ==> up to 19 chars */
42 /* total = 10 + 1 + 19 = 30 */
43
44 /* min length to determine MRCPv2 version */
45 #define MRCPV2_MIN_LENGTH 10
46 /* min length to determine MRCPv2 PDU length */
47 #define MRCPV2_MIN_PDU_LEN 30
48
49 /* line type */
50 typedef enum {
51 REQUEST_LINE,
52 RESPONSE_LINE,
53 EVENT_LINE,
54 UNKNOWN_LINE
55 } LINE_TYPE;
56
57 /* header type */
58 typedef enum {
59 UNKNOWN = 0,
60 ABORT_MODEL = 1,
61 ABORT_PHRASE_ENROLLMENT = 2,
62 ABORT_VERIFICATION = 3,
63 ACCEPT = 4,
64 ACCEPT_CHARSET = 5,
65 ACTIVE_REQUEST_ID_LIST = 6,
66 ADAPT_MODEL = 7,
67 AUDIO_FETCH_HINT = 8,
68 CACHE_CONTROL = 9,
69 CANCEL_IF_QUEUE = 10,
70 CAPTURE_ON_SPEECH = 11,
71 CHANNEL_IDENTIFIER = 12,
72 CLASH_THRESHOLD = 13,
73 CLEAR_DTMF_BUFFER = 14,
74 COMPLETION_CAUSE = 15,
75 COMPLETION_REASON = 16,
76 CONFIDENCE_THRESHOLD = 17,
77 CONFUSABLE_PHRASES_URI = 18,
78 CONSISTENCY_THRESHOLD = 19,
79 CONTENT_BASE = 20,
80 CONTENT_ENCODING = 21,
81 CONTENT_ID = 22,
82 CONTENT_LENGTH = 23,
83 CONTENT_LOCATION = 24,
84 CONTENT_TYPE = 25,
85 DTMF_BUFFER_TIME = 26,
86 DTMF_INTERDIGIT_TIMEOUT = 27,
87 DTMF_TERM_CHAR = 28,
88 DTMF_TERM_TIMEOUT = 29,
89 EARLY_NO_MATCH = 30,
90 ENROLL_UTTERANCE = 31,
91 FAILED_URI = 32,
92 FAILED_URI_CAUSE = 33,
93 FETCH_HINT = 34,
94 FETCH_TIMEOUT = 35,
95 FINAL_SILENCE = 36,
96 HOTWORD_MAX_DURATION = 37,
97 HOTWORD_MIN_DURATION = 38,
98 INPUT_TYPE = 39,
99 INPUT_WAVEFORM_URI = 40,
100 INTERPRET_TEXT = 41,
101 JUMP_SIZE = 42,
102 KILL_ON_BARGE_IN = 43,
103 LEXICON_SEARCH_ORDER = 44,
104 LOAD_LEXICON = 45,
105 LOGGING_TAG = 46,
106 MAX_TIME = 47,
107 MEDIA_TYPE = 48,
108 MIN_VERIFICATION_SCORE = 49,
109 N_BEST_LIST_LENGTH = 50,
110 NEW_AUDIO_CHANNEL = 51,
111 NEW_PHRASE_ID = 52,
112 NO_INPUT_TIMEOUT = 53,
113 NUM_MAX_VERIFICATION_PHRASES = 54,
114 NUM_MIN_CONSISTENT_PRONUNCIATIONS = 55,
115 NUM_MIN_VERIFICATION_PHRASES = 56,
116 PERSONAL_GRAMMAR_URI = 57,
117 PHRASE_ID = 58,
118 PHRASE_NL = 59,
119 PROSODY_CONTOUR = 60,
120 PROSODY_DURATION = 61,
121 PROSODY_PITCH = 62,
122 PROSODY_RANGE = 63,
123 PROSODY_RATE = 64,
124 PROSODY_VOLUME = 65,
125 PROXY_SYNC_ID = 66,
126 RECOGNITION_MODE = 67,
127 RECOGNITION_TIMEOUT = 68,
128 RECOGNIZER_CONTEXT_BLOCK = 69,
129 RECORD_URI = 70,
130 REPOSITORY_URI = 71,
131 SAVE_BEST_WAVEFORM = 72,
132 SAVE_WAVEFORM = 73,
133 SENSITIVITY_LEVEL = 74,
134 SET_COOKIE = 75,
135 SPEAK_LENGTH = 76,
136 SPEAK_RESTART = 77,
137 SPEAKER_PROFILE = 78,
138 SPEECH_COMPLETE_TIMEOUT = 79,
139 SPEECH_INCOMPLETE_TIMEOUT = 80,
140 SPEECH_LANGUAGE = 81,
141 SPEECH_MARKER = 82,
142 SPEED_VS_ACCURACY = 83,
143 START_INPUT_TIMERS = 84,
144 TRIM_LENGTH = 85,
145 VENDOR_SPECIFIC_PARAMETERS = 86,
146 VER_BUFFER_UTTERANCE = 87,
147 VERIFICATION_MODE = 88,
148 VOICE_AGE = 89,
149 VOICE_GENDER = 90,
150 VOICE_NAME = 91,
151 VOICE_VARIANT = 92,
152 VOICEPRINT_EXISTS = 93,
153 VOICEPRINT_IDENTIFIER = 94,
154 WAVEFORM_URI = 95,
155 WEIGHT = 96
156 } HEADER_TYPE;
157
158 static const value_string header_type_vals[] = {
159 { ABORT_MODEL, "abort-model" },
160 { ABORT_PHRASE_ENROLLMENT, "abort-phrase-enrollment" },
161 { ABORT_VERIFICATION, "abort-verification" },
162 { ACCEPT, "accept" },
163 { ACCEPT_CHARSET, "accept-charset" },
164 { ACTIVE_REQUEST_ID_LIST, "active-request-id-list" },
165 { ADAPT_MODEL, "adapt-model" },
166 { AUDIO_FETCH_HINT, "audio-fetch-hint" },
167 { CACHE_CONTROL, "cache-control" },
168 { CANCEL_IF_QUEUE, "cancel-if-queue" },
169 { CAPTURE_ON_SPEECH, "capture-on-speech" },
170 { CHANNEL_IDENTIFIER, "channel-identifier" },
171 { CLASH_THRESHOLD, "clash-threshold" },
172 { CLEAR_DTMF_BUFFER, "clear-dtmf-buffer" },
173 { COMPLETION_CAUSE, "completion-cause" },
174 { COMPLETION_REASON, "completion-reason" },
175 { CONFIDENCE_THRESHOLD, "confidence-threshold" },
176 { CONFUSABLE_PHRASES_URI, "confusable-phrases-uri" },
177 { CONSISTENCY_THRESHOLD, "consistency-threshold" },
178 { CONTENT_BASE, "content-base" },
179 { CONTENT_ENCODING, "content-encoding" },
180 { CONTENT_ID, "content-id" },
181 { CONTENT_LENGTH, "content-length" },
182 { CONTENT_LOCATION, "content-location" },
183 { CONTENT_TYPE, "content-type" },
184 { DTMF_BUFFER_TIME, "dtmf-buffer-time" },
185 { DTMF_INTERDIGIT_TIMEOUT, "dtmf-interdigit-timeout" },
186 { DTMF_TERM_CHAR, "dtmf-term-char" },
187 { DTMF_TERM_TIMEOUT, "dtmf-term-timeout" },
188 { EARLY_NO_MATCH, "early-no-match" },
189 { ENROLL_UTTERANCE, "enroll-utterance" },
190 { FAILED_URI, "failed-uri" },
191 { FAILED_URI_CAUSE, "failed-uri-cause" },
192 { FETCH_HINT, "fetch-hint" },
193 { FETCH_TIMEOUT, "fetch-timeout" },
194 { FINAL_SILENCE, "final-silence" },
195 { HOTWORD_MAX_DURATION, "hotword-max-duration" },
196 { HOTWORD_MIN_DURATION, "hotword-min-duration" },
197 { INPUT_TYPE, "input-type" },
198 { INPUT_WAVEFORM_URI, "input-waveform-uri" },
199 { INTERPRET_TEXT, "interpret-text" },
200 { JUMP_SIZE, "jump-size" },
201 { KILL_ON_BARGE_IN, "kill-on-barge-in" },
202 { LEXICON_SEARCH_ORDER, "lexicon-search-order" },
203 { LOAD_LEXICON, "load-lexicon" },
204 { LOGGING_TAG, "logging-tag" },
205 { MAX_TIME, "max-time" },
206 { MEDIA_TYPE, "media-type" },
207 { MIN_VERIFICATION_SCORE, "min-verification-score" },
208 { N_BEST_LIST_LENGTH, "n-best-list-length" },
209 { NEW_AUDIO_CHANNEL, "new-audio-channel" },
210 { NEW_PHRASE_ID, "new-phrase-id" },
211 { NO_INPUT_TIMEOUT, "no-input-timeout" },
212 { NUM_MAX_VERIFICATION_PHRASES, "num-max-verification-phrases" },
213 { NUM_MIN_CONSISTENT_PRONUNCIATIONS, "num-min-consistent-pronunciations" },
214 { NUM_MIN_VERIFICATION_PHRASES, "num-min-verification-phrases" },
215 { PERSONAL_GRAMMAR_URI, "personal-grammar-uri" },
216 { PHRASE_ID, "phrase-id" },
217 { PHRASE_NL, "phrase-nl" },
218 { PROSODY_CONTOUR, "prosody-contour" },
219 { PROSODY_DURATION, "prosody-duration" },
220 { PROSODY_PITCH, "prosody-pitch" },
221 { PROSODY_RANGE, "prosody-range" },
222 { PROSODY_RATE, "prosody-rate" },
223 { PROSODY_VOLUME, "prosody-volume" },
224 { PROXY_SYNC_ID, "proxy-sync-id" },
225 { RECOGNITION_MODE, "recognition-mode" },
226 { RECOGNITION_TIMEOUT, "recognition-timeout" },
227 { RECOGNIZER_CONTEXT_BLOCK, "recognizer-context-block" },
228 { RECORD_URI, "record-uri" },
229 { REPOSITORY_URI, "repository-uri" },
230 { SAVE_BEST_WAVEFORM, "save-best-waveform" },
231 { SAVE_WAVEFORM, "save-waveform" },
232 { SENSITIVITY_LEVEL, "sensitivity-level" },
233 { SET_COOKIE, "set-cookie" },
234 { SPEAK_LENGTH, "speak-length" },
235 { SPEAK_RESTART, "speak-restart" },
236 { SPEAKER_PROFILE, "speaker-profile" },
237 { SPEECH_COMPLETE_TIMEOUT, "speech-complete-timeout" },
238 { SPEECH_INCOMPLETE_TIMEOUT, "speech-incomplete-timeout" },
239 { SPEECH_LANGUAGE, "speech-language" },
240 { SPEECH_MARKER, "speech-marker" },
241 { SPEED_VS_ACCURACY, "speed-vs-accuracy" },
242 { START_INPUT_TIMERS, "start-input-timers" },
243 { TRIM_LENGTH, "trim-length" },
244 { VENDOR_SPECIFIC_PARAMETERS, "vendor-specific-parameters" },
245 { VER_BUFFER_UTTERANCE, "ver-buffer-utterance" },
246 { VERIFICATION_MODE, "verification-mode" },
247 { VOICE_AGE, "voice-age" },
248 { VOICE_GENDER, "voice-gender" },
249 { VOICE_NAME, "voice-name" },
250 { VOICE_VARIANT, "voice-variant" },
251 { VOICEPRINT_EXISTS, "voiceprint-exists" },
252 { VOICEPRINT_IDENTIFIER, "voiceprint-identifier" },
253 { WAVEFORM_URI, "waveform-uri" },
254 { WEIGHT, "weight" },
255 { 0, NULL }
256 };
257
258 /* Initialize the protocol and registered fields */
259 static int proto_mrcpv2 = -1;
260 static int hf_mrcpv2_Request_Line = -1;
261 static int hf_mrcpv2_Response_Line = -1;
262 static int hf_mrcpv2_Event_Line = -1;
263 static int hf_mrcpv2_Unknown_Message = -1;
264 static int hf_mrcpv2_Unknown_Header = -1;
265 static int hf_mrcpv2_Data = -1;
266 static int hf_mrcpv2_Method = -1;
267 static int hf_mrcpv2_Event = -1;
268 static int hf_mrcpv2_version = -1;
269 static int hf_mrcpv2_message_length = -1;
270 static int hf_mrcpv2_request_id = -1;
271 static int hf_mrcpv2_status_code = -1;
272 static int hf_mrcpv2_request_state = -1;
273 static int hf_mrcpv2_Abort_Model = -1;
274 static int hf_mrcpv2_Abort_Phrase_Enrollment = -1;
275 static int hf_mrcpv2_Abort_Verification = -1;
276 static int hf_mrcpv2_Accept = -1;
277 static int hf_mrcpv2_Accept_Charset = -1;
278 static int hf_mrcpv2_Active_Request_Id_List = -1;
279 static int hf_mrcpv2_Adapt_Model = -1;
280 static int hf_mrcpv2_Audio_Fetch_Hint = -1;
281 static int hf_mrcpv2_Cache_Control = -1;
282 static int hf_mrcpv2_Cancel_If_Queue = -1;
283 static int hf_mrcpv2_Capture_On_Speech = -1;
284 static int hf_mrcpv2_Channel_Identifier = -1;
285 static int hf_mrcpv2_Clash_Threshold = -1;
286 static int hf_mrcpv2_Clear_Dtmf_Buffer = -1;
287 static int hf_mrcpv2_Completion_Cause = -1;
288 static int hf_mrcpv2_Completion_Reason = -1;
289 static int hf_mrcpv2_Confidence_Threshold = -1;
290 static int hf_mrcpv2_Confusable_Phrases_URI = -1;
291 static int hf_mrcpv2_Consistency_Threshold = -1;
292 static int hf_mrcpv2_Content_Base = -1;
293 static int hf_mrcpv2_Content_Encoding = -1;
294 static int hf_mrcpv2_Content_ID = -1;
295 static int hf_mrcpv2_Content_Length = -1;
296 static int hf_mrcpv2_Content_Location = -1;
297 static int hf_mrcpv2_Content_Type = -1;
298 static int hf_mrcpv2_Dtmf_Buffer_Time = -1;
299 static int hf_mrcpv2_Dtmf_Interdigit_Timeout = -1;
300 static int hf_mrcpv2_Dtmf_Term_Char = -1;
301 static int hf_mrcpv2_Dtmf_Term_Timeout = -1;
302 static int hf_mrcpv2_Early_No_Match = -1;
303 static int hf_mrcpv2_Enroll_Utterance = -1;
304 static int hf_mrcpv2_Failed_URI = -1;
305 static int hf_mrcpv2_Failed_URI_Cause = -1;
306 static int hf_mrcpv2_Fetch_Hint = -1;
307 static int hf_mrcpv2_Fetch_Timeout = -1;
308 static int hf_mrcpv2_Final_Silence = -1;
309 static int hf_mrcpv2_Hotword_Max_Duration = -1;
310 static int hf_mrcpv2_Hotword_Min_Duration = -1;
311 static int hf_mrcpv2_Input_Type = -1;
312 static int hf_mrcpv2_Input_Waveform_URI = -1;
313 static int hf_mrcpv2_Interpret_Text = -1;
314 static int hf_mrcpv2_Jump_Size = -1;
315 static int hf_mrcpv2_Kill_On_Barge_In = -1;
316 static int hf_mrcpv2_Lexicon_Search_Order = -1;
317 static int hf_mrcpv2_Load_Lexicon = -1;
318 static int hf_mrcpv2_Logging_Tag = -1;
319 static int hf_mrcpv2_Max_Time = -1;
320 static int hf_mrcpv2_Media_Type = -1;
321 static int hf_mrcpv2_Min_Verification_Score = -1;
322 static int hf_mrcpv2_N_Best_List_Length = -1;
323 static int hf_mrcpv2_New_Audio_Channel = -1;
324 static int hf_mrcpv2_New_Phrase_ID = -1;
325 static int hf_mrcpv2_No_Input_Timeout = -1;
326 static int hf_mrcpv2_Num_Max_Verification_Phrases = -1;
327 static int hf_mrcpv2_Num_Min_Consistent_Pronunciations = -1;
328 static int hf_mrcpv2_Num_Min_Verification_Phrases = -1;
329 static int hf_mrcpv2_Personal_Grammar_URI = -1;
330 static int hf_mrcpv2_Phrase_ID = -1;
331 static int hf_mrcpv2_Phrase_NL = -1;
332 static int hf_mrcpv2_Prosody_Contour = -1;
333 static int hf_mrcpv2_Prosody_Duration = -1;
334 static int hf_mrcpv2_Prosody_Pitch = -1;
335 static int hf_mrcpv2_Prosody_Range = -1;
336 static int hf_mrcpv2_Prosody_Rate = -1;
337 static int hf_mrcpv2_Prosody_Volume = -1;
338 static int hf_mrcpv2_Proxy_Sync_Id = -1;
339 static int hf_mrcpv2_Recognition_Mode = -1;
340 static int hf_mrcpv2_Recognition_Timeout = -1;
341 static int hf_mrcpv2_Recognizer_Context_Block = -1;
342 static int hf_mrcpv2_Record_URI = -1;
343 static int hf_mrcpv2_Repository_URI = -1;
344 static int hf_mrcpv2_Save_Best_Waveform = -1;
345 static int hf_mrcpv2_Save_Waveform = -1;
346 static int hf_mrcpv2_Sensitivity_Level = -1;
347 static int hf_mrcpv2_Set_Cookie = -1;
348 static int hf_mrcpv2_Speak_Length = -1;
349 static int hf_mrcpv2_Speak_Restart = -1;
350 static int hf_mrcpv2_Speaker_Profile = -1;
351 static int hf_mrcpv2_Speech_Complete_Timeout = -1;
352 static int hf_mrcpv2_Speech_Incomplete_Timeout = -1;
353 static int hf_mrcpv2_Speech_Language = -1;
354 static int hf_mrcpv2_Speech_Marker = -1;
355 static int hf_mrcpv2_Speed_Vs_Accuracy = -1;
356 static int hf_mrcpv2_Start_Input_Timers = -1;
357 static int hf_mrcpv2_Trim_Length = -1;
358 static int hf_mrcpv2_Vendor_Specific_Parameters = -1;
359 static int hf_mrcpv2_Ver_Buffer_Utterance = -1;
360 static int hf_mrcpv2_Verification_Mode = -1;
361 static int hf_mrcpv2_Voice_Age = -1;
362 static int hf_mrcpv2_Voice_Gender = -1;
363 static int hf_mrcpv2_Voice_Name = -1;
364 static int hf_mrcpv2_Voice_Variant = -1;
365 static int hf_mrcpv2_Voiceprint_Exists = -1;
366 static int hf_mrcpv2_Voiceprint_Identifier = -1;
367 static int hf_mrcpv2_Waveform_URI = -1;
368 static int hf_mrcpv2_Weight = -1;
369
370 static expert_field ei_mrcpv2_Content_Length_invalid = EI_INIT;
371
372 /* Global MRCPv2 port pref */
373 #define TCP_DEFAULT_RANGE "6075, 30000-30200" /* Not IANA registered */
374
375 /* Initialize the subtree pointers */
376 static gint ett_mrcpv2 = -1;
377 static gint ett_Request_Line = -1;
378 static gint ett_Response_Line = -1;
379 static gint ett_Event_Line = -1;
380 static gint ett_Status_Code = -1;
381
382 /* format status code description */
383 static const string_string status_code_vals[] = {
384 { "200", "Success" },
385 { "201", "Success with some optional header fields ignored" },
386 { "401", "Client Failure: Method not allowed" },
387 { "402", "Client Failure: Method not valid in this state" },
388 { "403", "Client Failure: Unsupported header field" },
389 { "404", "Client Failure: Illegal value for header field. This is the error for a syntax violation." },
390 { "405", "Client Failure: Resource not allocated for this session or does not exist" },
391 { "406", "Client Failure: Mandatory Header Field Missing" },
392 { "407", "Client Failure: Method or Operation Failed (e.g., Grammar compilation failed in the recognizer. Detailed cause codes might be available through a resource specific header.)" },
393 { "408", "Client Failure: Unrecognized or unsupported message entity" },
394 { "409", "Client Failure: Unsupported Header Field Value. This is a value that is syntactically legal but exceeds the implementation's capabilities or expectations." },
395 { "410", "Client Failure: Non-Monotonic or Out of order sequence number in request." },
396 { "501", "Server Failure: Server Internal Error" },
397 { "502", "Server Failure: Protocol Version not supported" },
398 { "503", "Server Failure: Reserved for future assignment" },
399 { "504", "Server Failure: Message too large" },
400 { NULL, NULL }
401 };
402
403 /* Code to actually dissect the packets */
404 static int
dissect_mrcpv2_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree)405 dissect_mrcpv2_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
406 {
407 /* Set up structures needed to add the protocol subtree and manage it */
408 proto_item *ti;
409 proto_tree *mrcpv2_tree;
410 gint next_offset, linelen;
411 gint tvb_len;
412 gint pdu_size;
413 gint offset;
414 gint value_offset;
415 gint str_len;
416 gchar *header_name;
417 gchar *header_value;
418 LINE_TYPE line_type = UNKNOWN_LINE;
419 HEADER_TYPE header_type;
420 gint colon_offset;
421 gint content_length;
422 const value_string *p = NULL;
423 proto_item *line_item = NULL;
424 proto_item *request_line_item = NULL;
425 proto_item *response_line_item = NULL;
426 proto_item *event_line_item = NULL;
427 proto_item *status_code_item = NULL;
428 proto_item *pi = NULL;
429
430 gint sp_start;
431 gint sp_end;
432 guint8 *field1;
433 guint8 *field2;
434 guint8 *field3;
435 guint8 *field4;
436 guint8 *field5 = NULL;
437
438 /* Make entries in Protocol column and Info column on summary display */
439 col_set_str(pinfo->cinfo, COL_PROTOCOL, "MRCPv2");
440
441 offset = 0;
442 tvb_len = tvb_reported_length(tvb);
443
444 ti = proto_tree_add_item(tree, proto_mrcpv2, tvb, 0, -1, ENC_UTF_8);
445 mrcpv2_tree = proto_item_add_subtree(ti, ett_mrcpv2);
446
447 /* get first line */
448 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
449
450 /* find out MRCP message type:
451
452 request-line = mrcp-version SP message-length SP method-name SP request-id CRLF
453 response-line = mrcp-version SP message-length SP request-id SP status-code SP request-state CRLF
454 event-line = mrcp-version SP message-length SP event-name SP request-id SP request-state CRLF
455 */
456 /* version */
457 sp_end = tvb_find_guint8(tvb, 0, linelen, ' ');
458 if ((sp_end == -1) || (sp_end > tvb_len) || (sp_end > linelen))
459 return -1;
460 field1 = tvb_get_string_enc(pinfo->pool, tvb, 0, sp_end, ENC_ASCII);
461 sp_start = sp_end + 1;
462
463 /* length */
464 sp_end = tvb_find_guint8(tvb, sp_start, linelen - sp_start, ' ');
465 if ((sp_end == -1) || (sp_end > tvb_len) || (sp_end > linelen))
466 return -1;
467 field2 = tvb_get_string_enc(pinfo->pool, tvb, sp_start, sp_end - sp_start, ENC_ASCII);
468 sp_start = sp_end + 1;
469
470 /* method, request ID or event */
471 sp_end = tvb_find_guint8(tvb, sp_start, linelen - sp_start, ' ');
472 if ((sp_end == -1) || (sp_end > tvb_len) || (sp_end > linelen))
473 return -1;
474 field3 = tvb_get_string_enc(pinfo->pool, tvb, sp_start, sp_end - sp_start, ENC_ASCII);
475 sp_start = sp_end + 1;
476
477 /* request ID or status code */
478 sp_end = tvb_find_guint8(tvb, sp_start, linelen - sp_start, ' ');
479 if (sp_end == -1)
480 {
481 field4 = tvb_get_string_enc(pinfo->pool, tvb, sp_start, linelen - sp_start, ENC_ASCII);
482 line_type = REQUEST_LINE; /* only request line has 4 parameters */
483 }
484 else
485 {
486 if ((sp_end > tvb_len) || (sp_end > linelen))
487 return -1;
488 field4 = tvb_get_string_enc(pinfo->pool, tvb, sp_start, sp_end - sp_start, ENC_ASCII);
489
490 if (g_ascii_isdigit(field3[0])) /* request ID is number, so it has to be response */
491 line_type = RESPONSE_LINE;
492 else
493 line_type = EVENT_LINE;
494
495 sp_start = sp_end + 1;
496 sp_end = linelen;
497 if ((sp_end > tvb_len) || (sp_end > linelen))
498 return -1;
499 field5 = tvb_get_string_enc(pinfo->pool, tvb, sp_start, sp_end - sp_start, ENC_ASCII);
500 }
501
502 /* check pdu size */
503 if (!ws_strtou32(field2, NULL, &pdu_size) || pdu_size > tvb_len)
504 return -1;
505
506 /* process MRCP header line */
507 switch(line_type){
508 case REQUEST_LINE:
509 {
510 col_set_str(pinfo->cinfo, COL_INFO, "Request: ");
511 line_item = proto_tree_add_item(mrcpv2_tree, hf_mrcpv2_Request_Line, tvb, offset, linelen, ENC_UTF_8|ENC_NA);
512 request_line_item = proto_item_add_subtree(line_item, ett_Request_Line);
513 /* version */
514 str_len = (gint)strlen(field1);
515 proto_tree_add_item(request_line_item, hf_mrcpv2_version, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
516 offset += str_len + 1; /* add SP */
517 /* message length */
518 str_len = (gint)strlen(field2);
519 proto_tree_add_item(request_line_item, hf_mrcpv2_message_length, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
520 offset += str_len + 1; /* add SP */
521 /* method name */
522 col_append_str(pinfo->cinfo, COL_INFO, field3);
523 str_len = (gint)strlen(field3);
524 proto_tree_add_item(request_line_item, hf_mrcpv2_Method, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
525 offset += str_len + 1; /* add SP */
526 /* request ID */
527 str_len = (gint)strlen(field4);
528 proto_tree_add_item(request_line_item, hf_mrcpv2_request_id, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
529 /*offset += str_len + 2;*/ /* add CRLF */
530 }
531 break;
532 case RESPONSE_LINE:
533 {
534 col_set_str(pinfo->cinfo, COL_INFO, "Response: ");
535 line_item = proto_tree_add_item(mrcpv2_tree, hf_mrcpv2_Response_Line, tvb, offset, linelen, ENC_UTF_8|ENC_NA);
536 response_line_item = proto_item_add_subtree(line_item, ett_Response_Line);
537 /* version */
538 str_len = (gint)strlen(field1);
539 proto_tree_add_item(response_line_item, hf_mrcpv2_version, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
540 offset += str_len + 1; /* add SP */
541 /* message length */
542 str_len = (gint)strlen(field2);
543 proto_tree_add_item(response_line_item, hf_mrcpv2_message_length, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
544 offset += str_len + 1; /* add SP */
545 /* request ID */
546 str_len = (gint)strlen(field3);
547 proto_tree_add_item(response_line_item, hf_mrcpv2_request_id, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
548 offset += str_len + 1; /* add SP */
549 /* status code */
550 str_len = (gint)strlen(field4);
551 status_code_item = proto_tree_add_item(response_line_item, hf_mrcpv2_status_code, tvb, offset,
552 str_len, ENC_UTF_8|ENC_NA);
553 proto_item_append_text(status_code_item, " %s", str_to_str(field4, status_code_vals, "Unknown Status Code"));
554 offset += str_len + 1; /* add SP */
555 /* request state */
556 col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) %s", field4, field5);
557 str_len = (gint)strlen(field5);
558 proto_tree_add_item(response_line_item, hf_mrcpv2_request_state, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
559 /*offset += str_len + 2;*/ /* add CRLF */
560 }
561 break;
562 case EVENT_LINE:
563 {
564 col_set_str(pinfo->cinfo, COL_INFO, "Event: ");
565 line_item = proto_tree_add_item(mrcpv2_tree, hf_mrcpv2_Event_Line, tvb, offset, linelen, ENC_UTF_8|ENC_NA);
566 event_line_item = proto_item_add_subtree(line_item, ett_Event_Line);
567 /* version */
568 str_len = (gint)strlen(field1);
569 proto_tree_add_item(event_line_item, hf_mrcpv2_version, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
570 offset += str_len + 1; /* add SP */
571 /* message length */
572 str_len = (gint)strlen(field2);
573 proto_tree_add_item(event_line_item, hf_mrcpv2_message_length, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
574 offset += str_len + 1; /* add SP */
575 /* event name */
576 col_append_str(pinfo->cinfo, COL_INFO, field3);
577 str_len = (gint)strlen(field3);
578 proto_tree_add_item(event_line_item, hf_mrcpv2_Event, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
579 offset += str_len + 1; /* add SP */
580 /* request ID */
581 str_len = (gint)strlen(field4);
582 proto_tree_add_item(event_line_item, hf_mrcpv2_request_id, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
583 offset += str_len + 1; /* add SP */
584 /* request state */
585 str_len = (gint)strlen(field5);
586 proto_tree_add_item(event_line_item, hf_mrcpv2_request_state, tvb, offset, str_len, ENC_UTF_8|ENC_NA);
587 /*offset += str_len + 2;*/ /* add CRLF */
588 }
589 break;
590 default:
591 {
592 /* mark whole packet as unknown and return */
593 col_set_str(pinfo->cinfo, COL_INFO, "UNKNOWN message");
594 proto_tree_add_item(mrcpv2_tree, hf_mrcpv2_Unknown_Message, tvb, offset, tvb_len, ENC_UTF_8|ENC_NA);
595 return tvb_len;
596 }
597 }
598
599 if (tree) {
600 /* process the rest of the header lines here */
601 content_length = 0;
602 while (tvb_offset_exists(tvb, next_offset))
603 {
604 /* get next line */
605 offset = next_offset;
606 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
607
608 /* blank line separates msg header and msg body */
609 if (linelen == 0)
610 {
611 if (content_length > 0)
612 { /* content length > 0 and CRLF detected, this has to be msg body */
613 offset += 2; /* skip separating CRLF */
614 proto_tree_add_item(mrcpv2_tree, hf_mrcpv2_Data, tvb, offset, tvb_len - offset, ENC_ASCII|ENC_NA);
615 next_offset = tvb_len; /* we are done */
616 }
617 continue;
618 }
619
620 /* get header type and its value */
621 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
622 if (colon_offset == -1)
623 { /* header type should end with ':' */
624 proto_tree_add_item(mrcpv2_tree, hf_mrcpv2_Unknown_Header, tvb, offset, linelen, ENC_UTF_8|ENC_NA);
625 continue;
626 }
627 header_name = tvb_get_string_enc(pinfo->pool, tvb, offset, colon_offset - offset, ENC_ASCII);
628 ascii_strdown_inplace(header_name);
629 value_offset = tvb_skip_wsp(tvb, colon_offset + 1, offset + linelen - (colon_offset + 1));
630 header_value = tvb_get_string_enc(pinfo->pool, tvb, value_offset, offset + linelen - value_offset, ENC_ASCII);
631
632 /* find out header type */
633 header_type = UNKNOWN;
634 for (p = header_type_vals; p->strptr != NULL; ++p)
635 {
636 if (strncmp(p->strptr, header_name, strlen(p->strptr)) == 0)
637 {
638 header_type = (HEADER_TYPE)p->value;
639 break;
640 }
641 }
642
643 /* add header type and value into the tree */
644 switch (header_type)
645 {
646 case ABORT_MODEL:
647 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Abort_Model, tvb, offset, linelen, header_value);
648 break;
649 case ABORT_PHRASE_ENROLLMENT:
650 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Abort_Phrase_Enrollment, tvb, offset, linelen, header_value);
651 break;
652 case ABORT_VERIFICATION:
653 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Abort_Verification, tvb, offset, linelen, header_value);
654 break;
655 case ACCEPT:
656 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Accept, tvb, offset, linelen, header_value);
657 break;
658 case ACCEPT_CHARSET:
659 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Accept_Charset, tvb, offset, linelen, header_value);
660 break;
661 case ACTIVE_REQUEST_ID_LIST:
662 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Active_Request_Id_List, tvb, offset, linelen, header_value);
663 break;
664 case ADAPT_MODEL:
665 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Adapt_Model, tvb, offset, linelen, header_value);
666 break;
667 case AUDIO_FETCH_HINT:
668 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Audio_Fetch_Hint, tvb, offset, linelen, header_value);
669 break;
670 case CACHE_CONTROL:
671 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Cache_Control, tvb, offset, linelen, header_value);
672 break;
673 case CANCEL_IF_QUEUE:
674 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Cancel_If_Queue, tvb, offset, linelen, header_value);
675 break;
676 case CAPTURE_ON_SPEECH:
677 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Capture_On_Speech, tvb, offset, linelen, header_value);
678 break;
679 case CHANNEL_IDENTIFIER:
680 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Channel_Identifier, tvb, offset, linelen, header_value);
681 break;
682 case CLASH_THRESHOLD:
683 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Clash_Threshold, tvb, offset, linelen, header_value);
684 break;
685 case CLEAR_DTMF_BUFFER:
686 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Clear_Dtmf_Buffer, tvb, offset, linelen, header_value);
687 break;
688 case COMPLETION_CAUSE:
689 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Completion_Cause, tvb, offset, linelen, header_value);
690 break;
691 case COMPLETION_REASON:
692 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Completion_Reason, tvb, offset, linelen, header_value);
693 break;
694 case CONFIDENCE_THRESHOLD:
695 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Confidence_Threshold, tvb, offset, linelen, header_value);
696 break;
697 case CONFUSABLE_PHRASES_URI:
698 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Confusable_Phrases_URI, tvb, offset, linelen, header_value);
699 break;
700 case CONSISTENCY_THRESHOLD:
701 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Consistency_Threshold, tvb, offset, linelen, header_value);
702 break;
703 case CONTENT_BASE:
704 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Content_Base, tvb, offset, linelen, header_value);
705 break;
706 case CONTENT_ENCODING:
707 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Content_Encoding, tvb, offset, linelen, header_value);
708 break;
709 case CONTENT_ID:
710 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Content_ID, tvb, offset, linelen, header_value);
711 break;
712 case CONTENT_LENGTH:
713 pi = proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Content_Length, tvb, offset, linelen, header_value);
714 /* if content length is > 0, then there are some data after the headers */
715 if (!ws_strtou32(header_value, NULL, &content_length)) {
716 content_length = 0;
717 expert_add_info(pinfo, pi, &ei_mrcpv2_Content_Length_invalid);
718 }
719 break;
720 case CONTENT_LOCATION:
721 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Content_Location, tvb, offset, linelen, header_value);
722 break;
723 case CONTENT_TYPE:
724 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Content_Type, tvb, offset, linelen, header_value);
725 break;
726 case DTMF_BUFFER_TIME:
727 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Dtmf_Buffer_Time, tvb, offset, linelen, header_value);
728 break;
729 case DTMF_INTERDIGIT_TIMEOUT:
730 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Dtmf_Interdigit_Timeout, tvb, offset, linelen, header_value);
731 break;
732 case DTMF_TERM_CHAR:
733 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Dtmf_Term_Char, tvb, offset, linelen, header_value);
734 break;
735 case DTMF_TERM_TIMEOUT:
736 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Dtmf_Term_Timeout, tvb, offset, linelen, header_value);
737 break;
738 case EARLY_NO_MATCH:
739 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Early_No_Match, tvb, offset, linelen, header_value);
740 break;
741 case ENROLL_UTTERANCE:
742 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Enroll_Utterance, tvb, offset, linelen, header_value);
743 break;
744 case FAILED_URI:
745 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Failed_URI, tvb, offset, linelen, header_value);
746 break;
747 case FAILED_URI_CAUSE:
748 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Failed_URI_Cause, tvb, offset, linelen, header_value);
749 break;
750 case FETCH_HINT:
751 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Fetch_Hint, tvb, offset, linelen, header_value);
752 break;
753 case FETCH_TIMEOUT:
754 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Fetch_Timeout, tvb, offset, linelen, header_value);
755 break;
756 case FINAL_SILENCE:
757 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Final_Silence, tvb, offset, linelen, header_value);
758 break;
759 case HOTWORD_MAX_DURATION:
760 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Hotword_Max_Duration, tvb, offset, linelen, header_value);
761 break;
762 case HOTWORD_MIN_DURATION:
763 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Hotword_Min_Duration, tvb, offset, linelen, header_value);
764 break;
765 case INPUT_TYPE:
766 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Input_Type, tvb, offset, linelen, header_value);
767 break;
768 case INPUT_WAVEFORM_URI:
769 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Input_Waveform_URI, tvb, offset, linelen, header_value);
770 break;
771 case INTERPRET_TEXT:
772 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Interpret_Text, tvb, offset, linelen, header_value);
773 break;
774 case JUMP_SIZE:
775 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Jump_Size, tvb, offset, linelen, header_value);
776 break;
777 case KILL_ON_BARGE_IN:
778 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Kill_On_Barge_In, tvb, offset, linelen, header_value);
779 break;
780 case LEXICON_SEARCH_ORDER:
781 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Lexicon_Search_Order, tvb, offset, linelen, header_value);
782 break;
783 case LOAD_LEXICON:
784 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Load_Lexicon, tvb, offset, linelen, header_value);
785 break;
786 case LOGGING_TAG:
787 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Logging_Tag, tvb, offset, linelen, header_value);
788 break;
789 case MAX_TIME:
790 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Max_Time, tvb, offset, linelen, header_value);
791 break;
792 case MEDIA_TYPE:
793 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Media_Type, tvb, offset, linelen, header_value);
794 break;
795 case MIN_VERIFICATION_SCORE:
796 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Min_Verification_Score, tvb, offset, linelen, header_value);
797 break;
798 case N_BEST_LIST_LENGTH:
799 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_N_Best_List_Length, tvb, offset, linelen, header_value);
800 break;
801 case NEW_AUDIO_CHANNEL:
802 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_New_Audio_Channel, tvb, offset, linelen, header_value);
803 break;
804 case NEW_PHRASE_ID:
805 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_New_Phrase_ID, tvb, offset, linelen, header_value);
806 break;
807 case NO_INPUT_TIMEOUT:
808 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_No_Input_Timeout, tvb, offset, linelen, header_value);
809 break;
810 case NUM_MAX_VERIFICATION_PHRASES:
811 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Num_Max_Verification_Phrases, tvb, offset, linelen, header_value);
812 break;
813 case NUM_MIN_CONSISTENT_PRONUNCIATIONS:
814 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Num_Min_Consistent_Pronunciations, tvb, offset, linelen, header_value);
815 break;
816 case NUM_MIN_VERIFICATION_PHRASES:
817 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Num_Min_Verification_Phrases, tvb, offset, linelen, header_value);
818 break;
819 case PERSONAL_GRAMMAR_URI:
820 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Personal_Grammar_URI, tvb, offset, linelen, header_value);
821 break;
822 case PHRASE_ID:
823 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Phrase_ID, tvb, offset, linelen, header_value);
824 break;
825 case PHRASE_NL:
826 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Phrase_NL, tvb, offset, linelen, header_value);
827 break;
828 case PROSODY_CONTOUR:
829 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Prosody_Contour, tvb, offset, linelen, header_value);
830 break;
831 case PROSODY_DURATION:
832 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Prosody_Duration, tvb, offset, linelen, header_value);
833 break;
834 case PROSODY_PITCH:
835 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Prosody_Pitch, tvb, offset, linelen, header_value);
836 break;
837 case PROSODY_RANGE:
838 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Prosody_Range, tvb, offset, linelen, header_value);
839 break;
840 case PROSODY_RATE:
841 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Prosody_Rate, tvb, offset, linelen, header_value);
842 break;
843 case PROSODY_VOLUME:
844 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Prosody_Volume, tvb, offset, linelen, header_value);
845 break;
846 case PROXY_SYNC_ID:
847 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Proxy_Sync_Id, tvb, offset, linelen, header_value);
848 break;
849 case RECOGNITION_MODE:
850 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Recognition_Mode, tvb, offset, linelen, header_value);
851 break;
852 case RECOGNITION_TIMEOUT:
853 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Recognition_Timeout, tvb, offset, linelen, header_value);
854 break;
855 case RECOGNIZER_CONTEXT_BLOCK:
856 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Recognizer_Context_Block, tvb, offset, linelen, header_value);
857 break;
858 case RECORD_URI:
859 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Record_URI, tvb, offset, linelen, header_value);
860 break;
861 case REPOSITORY_URI:
862 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Repository_URI, tvb, offset, linelen, header_value);
863 break;
864 case SAVE_BEST_WAVEFORM:
865 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Save_Best_Waveform, tvb, offset, linelen, header_value);
866 break;
867 case SAVE_WAVEFORM:
868 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Save_Waveform, tvb, offset, linelen, header_value);
869 break;
870 case SENSITIVITY_LEVEL:
871 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Sensitivity_Level, tvb, offset, linelen, header_value);
872 break;
873 case SET_COOKIE:
874 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Set_Cookie, tvb, offset, linelen, header_value);
875 break;
876 case SPEAK_LENGTH:
877 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Speak_Length, tvb, offset, linelen, header_value);
878 break;
879 case SPEAK_RESTART:
880 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Speak_Restart, tvb, offset, linelen, header_value);
881 break;
882 case SPEAKER_PROFILE:
883 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Speaker_Profile, tvb, offset, linelen, header_value);
884 break;
885 case SPEECH_COMPLETE_TIMEOUT:
886 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Speech_Complete_Timeout, tvb, offset, linelen, header_value);
887 break;
888 case SPEECH_INCOMPLETE_TIMEOUT:
889 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Speech_Incomplete_Timeout, tvb, offset, linelen, header_value);
890 break;
891 case SPEECH_LANGUAGE:
892 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Speech_Language, tvb, offset, linelen, header_value);
893 break;
894 case SPEECH_MARKER:
895 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Speech_Marker, tvb, offset, linelen, header_value);
896 break;
897 case SPEED_VS_ACCURACY:
898 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Speed_Vs_Accuracy, tvb, offset, linelen, header_value);
899 break;
900 case START_INPUT_TIMERS:
901 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Start_Input_Timers, tvb, offset, linelen, header_value);
902 break;
903 case TRIM_LENGTH:
904 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Trim_Length, tvb, offset, linelen, header_value);
905 break;
906 case VENDOR_SPECIFIC_PARAMETERS:
907 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Vendor_Specific_Parameters, tvb, offset, linelen, header_value);
908 break;
909 case VER_BUFFER_UTTERANCE:
910 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Ver_Buffer_Utterance, tvb, offset, linelen, header_value);
911 break;
912 case VERIFICATION_MODE:
913 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Verification_Mode, tvb, offset, linelen, header_value);
914 break;
915 case VOICE_AGE:
916 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Voice_Age, tvb, offset, linelen, header_value);
917 break;
918 case VOICE_GENDER:
919 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Voice_Gender, tvb, offset, linelen, header_value);
920 break;
921 case VOICE_NAME:
922 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Voice_Name, tvb, offset, linelen, header_value);
923 break;
924 case VOICE_VARIANT:
925 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Voice_Variant, tvb, offset, linelen, header_value);
926 break;
927 case VOICEPRINT_EXISTS:
928 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Voiceprint_Exists, tvb, offset, linelen, header_value);
929 break;
930 case VOICEPRINT_IDENTIFIER:
931 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Voiceprint_Identifier, tvb, offset, linelen, header_value);
932 break;
933 case WAVEFORM_URI:
934 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Waveform_URI, tvb, offset, linelen, header_value);
935 break;
936 case WEIGHT:
937 proto_tree_add_string(mrcpv2_tree, hf_mrcpv2_Weight, tvb, offset, linelen, header_value);
938 break;
939 default:
940 proto_tree_add_item(mrcpv2_tree, hf_mrcpv2_Unknown_Header, tvb, offset, linelen, ENC_UTF_8|ENC_NA);
941 break;
942 }
943 }
944 }
945
946 /* Return the amount of data this dissector was able to dissect */
947 return tvb_captured_length(tvb);
948 }
949
950 /* get the length of the MRCP message */
951 static guint
get_mrcpv2_pdu_len(packet_info * pinfo _U_,tvbuff_t * tvb,int offset,void * data _U_)952 get_mrcpv2_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_)
953 {
954 gint len_start;
955 gint len_end;
956 guint8 *msg_len;
957 guint num_msg_len = 0;
958
959 /* first string is version */
960 len_start = tvb_find_guint8(tvb, offset, MRCPV2_MIN_PDU_LEN, ' ');
961 if (len_start == -1)
962 return 0;
963 len_start += 1; /* skip whitespace */
964
965 /* second string is message length */
966 len_end = tvb_find_guint8(tvb, len_start, MRCPV2_MIN_PDU_LEN - len_start, ' ');
967 if (len_end == -1)
968 msg_len = tvb_get_string_enc(pinfo->pool, tvb, len_start, MRCPV2_MIN_PDU_LEN - len_start, ENC_ASCII);
969 else
970 msg_len = tvb_get_string_enc(pinfo->pool, tvb, len_start, len_end - len_start, ENC_ASCII);
971
972 ws_strtou32(msg_len, NULL, &num_msg_len);
973 return num_msg_len;
974 }
975
976 static int
dissect_mrcpv2_tcp_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)977 dissect_mrcpv2_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
978 {
979 return dissect_mrcpv2_common(tvb, pinfo, tree);
980 }
981
982 static int
dissect_mrcpv2_tcp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data)983 dissect_mrcpv2_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
984 {
985 gint len;
986 gint value_size;
987 guint8 *version;
988 guint8 *major;
989 guint8 *minor;
990 gint slash_offset;
991 gint dot_offset;
992 gint sp_offset;
993 int value;
994
995 len = tvb_captured_length(tvb);
996 if (len < MRCPV2_MIN_LENGTH) /* too short, can't conclude if it's mrcp */
997 return 0;
998
999 /* we are looking for MRCP string */
1000 slash_offset = tvb_find_guint8(tvb, 0, MRCPV2_MIN_LENGTH, '/');
1001 if (slash_offset != 4)
1002 return 0;
1003 version = tvb_get_string_enc(pinfo->pool, tvb, 0, slash_offset, ENC_ASCII);
1004 if (strcmp(version, "MRCP") != 0)
1005 return 0;
1006
1007 /* get first digit after the '/'; it should be 2 */
1008 dot_offset = tvb_find_guint8(tvb, slash_offset + 1, MRCPV2_MIN_LENGTH - slash_offset - 1, '.');
1009 if (dot_offset == -1)
1010 return 0;
1011 value_size = dot_offset - slash_offset - 1;
1012 if ((value_size != 1) && (value_size != 2))
1013 return 0;
1014 major = tvb_get_string_enc(pinfo->pool, tvb, slash_offset + 1, value_size, ENC_ASCII);
1015 if (!ws_strtou32(major, NULL, &value) || value != 2)
1016 return 0;
1017
1018 /* get second digit, it should be 0 */
1019 sp_offset = tvb_find_guint8(tvb, dot_offset + 1, MRCPV2_MIN_LENGTH - dot_offset - 1, ' ');
1020 if (sp_offset == -1)
1021 {
1022 minor = tvb_get_string_enc(pinfo->pool, tvb, dot_offset + 1, MRCPV2_MIN_LENGTH - dot_offset - 1, ENC_ASCII);
1023 len = MRCPV2_MIN_LENGTH;
1024 }
1025 else
1026 {
1027 minor = tvb_get_string_enc(pinfo->pool, tvb, dot_offset + 1, MRCPV2_MIN_LENGTH - sp_offset - 1, ENC_ASCII);
1028 len = sp_offset;
1029 }
1030 if (!ws_strtou32(minor, NULL, &value) || value != 0)
1031 return 0;
1032
1033 /* if we are here, then we have MRCP v 2.0 protocol, so proceed with the dissection */
1034 tcp_dissect_pdus(tvb, pinfo, tree, TRUE, MRCPV2_MIN_PDU_LEN,
1035 get_mrcpv2_pdu_len,
1036 dissect_mrcpv2_tcp_pdu, data);
1037 return len;
1038 }
1039
1040 void
proto_register_mrcpv2(void)1041 proto_register_mrcpv2(void)
1042 {
1043 expert_module_t* expert_mrcpv2;
1044
1045 static hf_register_info hf[] = {
1046 { &hf_mrcpv2_Request_Line,
1047 { "Request-Line", "mrcpv2.Request-Line",
1048 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1049 },
1050 { &hf_mrcpv2_Response_Line,
1051 { "Response-Line", "mrcpv2.Response-Line",
1052 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1053 },
1054 { &hf_mrcpv2_Event_Line,
1055 { "Event-Line", "mrcpv2.Event-Line",
1056 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1057 },
1058 { &hf_mrcpv2_Unknown_Message,
1059 { "Unknown Message", "mrcpv2.Unknown-Message",
1060 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1061 },
1062 { &hf_mrcpv2_Unknown_Header,
1063 { "Unknown Header", "mrcpv2.Unknown-Header",
1064 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1065 },
1066 { &hf_mrcpv2_Data,
1067 { "Message data", "mrcpv2.Data",
1068 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1069 },
1070 { &hf_mrcpv2_Method,
1071 { "Method", "mrcpv2.Method",
1072 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1073 },
1074 { &hf_mrcpv2_Event,
1075 { "Event", "mrcpv2.Event",
1076 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1077 },
1078 { &hf_mrcpv2_version,
1079 { "Version", "mrcpv2.Version",
1080 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1081 },
1082 { &hf_mrcpv2_message_length,
1083 { "Message Length", "mrcpv2.msg_len",
1084 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1085 },
1086 { &hf_mrcpv2_request_id,
1087 { "Request ID", "mrcpv2.reqID",
1088 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1089 },
1090 { &hf_mrcpv2_status_code,
1091 { "Status Code", "mrcpv2.status_code",
1092 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1093 },
1094 { &hf_mrcpv2_request_state,
1095 { "Request State", "mrcpv2.request_state",
1096 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }
1097 },
1098 { &hf_mrcpv2_Abort_Model,
1099 { "Abort-Model", "mrcpv2.Abort-Model",
1100 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1101 },
1102 { &hf_mrcpv2_Abort_Phrase_Enrollment,
1103 { "Abort-Phrase-Enrollment", "mrcpv2.Abort-Phrase-Enrollment",
1104 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1105 },
1106 { &hf_mrcpv2_Abort_Verification,
1107 { "Abort-Verification", "mrcpv2.Abort-Verification",
1108 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1109 },
1110 { &hf_mrcpv2_Accept,
1111 { "Accept", "mrcpv2.Accept",
1112 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1113 },
1114 { &hf_mrcpv2_Accept_Charset,
1115 { "Accept-Charset", "mrcpv2.Accept-Charset",
1116 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1117 },
1118 { &hf_mrcpv2_Active_Request_Id_List,
1119 { "Active-Request-Id-List", "mrcpv2.Active-Request-Id-List",
1120 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1121 },
1122 { &hf_mrcpv2_Adapt_Model,
1123 { "Adapt-Model", "mrcpv2.Adapt-Model",
1124 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1125 },
1126 { &hf_mrcpv2_Audio_Fetch_Hint,
1127 { "Audio-Fetch-Hint", "mrcpv2.Audio-Fetch-Hint",
1128 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1129 },
1130 { &hf_mrcpv2_Cache_Control,
1131 { "Cache-Control", "mrcpv2.Cache-Control",
1132 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1133 },
1134 { &hf_mrcpv2_Cancel_If_Queue,
1135 { "Cancel-If-Queue", "mrcpv2.Cancel-If-Queue",
1136 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1137 },
1138 { &hf_mrcpv2_Capture_On_Speech,
1139 { "Capture-On-Speech", "mrcpv2.Capture-On-Speech",
1140 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1141 },
1142 { &hf_mrcpv2_Channel_Identifier,
1143 { "Channel-Identifier", "mrcpv2.Channel-Identifier",
1144 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1145 },
1146 { &hf_mrcpv2_Clash_Threshold,
1147 { "Clash-Threshold", "mrcpv2.Clash-Threshold",
1148 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1149 },
1150 { &hf_mrcpv2_Clear_Dtmf_Buffer,
1151 { "Clear-Dtmf-Buffer", "mrcpv2.Clear-Dtmf-Buffer",
1152 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1153 },
1154 { &hf_mrcpv2_Completion_Cause,
1155 { "Completion-Cause", "mrcpv2.Completion-Cause",
1156 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1157 },
1158 { &hf_mrcpv2_Completion_Reason,
1159 { "Completion-Reason", "mrcpv2.Completion-Reason",
1160 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1161 },
1162 { &hf_mrcpv2_Confidence_Threshold,
1163 { "Confidence-Threshold", "mrcpv2.Confidence-Threshold",
1164 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1165 },
1166 { &hf_mrcpv2_Confusable_Phrases_URI,
1167 { "Confusable-Phrases-URI", "mrcpv2.Confusable-Phrases-URI",
1168 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1169 },
1170 { &hf_mrcpv2_Consistency_Threshold,
1171 { "Consistency-Threshold", "mrcpv2.Consistency-Threshold",
1172 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1173 },
1174 { &hf_mrcpv2_Content_Base,
1175 { "Content-Base", "mrcpv2.Content-Base",
1176 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1177 },
1178 { &hf_mrcpv2_Content_Encoding,
1179 { "Content-Encoding", "mrcpv2.Content-Encoding",
1180 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1181 },
1182 { &hf_mrcpv2_Content_ID,
1183 { "Content-ID", "mrcpv2.Content-ID",
1184 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1185 },
1186 { &hf_mrcpv2_Content_Length,
1187 { "Content-Length", "mrcpv2.Content-Length",
1188 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1189 },
1190 { &hf_mrcpv2_Content_Location,
1191 { "Content-Location", "mrcpv2.Content-Location",
1192 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1193 },
1194 { &hf_mrcpv2_Content_Type,
1195 { "Content-Type", "mrcpv2.Content-Type",
1196 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1197 },
1198 { &hf_mrcpv2_Dtmf_Buffer_Time,
1199 { "Dtmf-Buffer-Time", "mrcpv2.Dtmf-Buffer-Time",
1200 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1201 },
1202 { &hf_mrcpv2_Dtmf_Interdigit_Timeout,
1203 { "Dtmf-Interdigit-Timeout", "mrcpv2.Dtmf-Interdigit-Timeout",
1204 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1205 },
1206 { &hf_mrcpv2_Dtmf_Term_Char,
1207 { "Dtmf-Term-Char", "mrcpv2.Dtmf-Term-Char",
1208 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1209 },
1210 { &hf_mrcpv2_Dtmf_Term_Timeout,
1211 { "Dtmf-Term-Timeout", "mrcpv2.Dtmf-Term-Timeout",
1212 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1213 },
1214 { &hf_mrcpv2_Early_No_Match,
1215 { "Early-No-Match", "mrcpv2.Early-No-Match",
1216 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1217 },
1218 { &hf_mrcpv2_Enroll_Utterance,
1219 { "Enroll-Utterance", "mrcpv2.Enroll-Utterance",
1220 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1221 },
1222 { &hf_mrcpv2_Failed_URI,
1223 { "Failed-URI", "mrcpv2.Failed-URI",
1224 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1225 },
1226 { &hf_mrcpv2_Failed_URI_Cause,
1227 { "Failed-URI-Cause", "mrcpv2.Failed-URI-Cause",
1228 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1229 },
1230 { &hf_mrcpv2_Fetch_Hint,
1231 { "Fetch-Hint", "mrcpv2.Fetch-Hint",
1232 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1233 },
1234 { &hf_mrcpv2_Fetch_Timeout,
1235 { "Fetch-Timeout", "mrcpv2.Fetch-Timeout",
1236 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1237 },
1238 { &hf_mrcpv2_Final_Silence,
1239 { "Final-Silence", "mrcpv2.Final-Silence",
1240 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1241 },
1242 { &hf_mrcpv2_Hotword_Max_Duration,
1243 { "Hotword-Max-Duration", "mrcpv2.Hotword-Max-Duration",
1244 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1245 },
1246 { &hf_mrcpv2_Hotword_Min_Duration,
1247 { "Hotword-Min-Duration", "mrcpv2.Hotword-Min-Duration",
1248 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1249 },
1250 { &hf_mrcpv2_Input_Type,
1251 { "Input-Type", "mrcpv2.Input-Type",
1252 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1253 },
1254 { &hf_mrcpv2_Input_Waveform_URI,
1255 { "Input-Waveform-URI", "mrcpv2.Input-Waveform-URI",
1256 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1257 },
1258 { &hf_mrcpv2_Interpret_Text,
1259 { "Interpret-Text", "mrcpv2.Interpret-Text",
1260 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1261 },
1262 { &hf_mrcpv2_Jump_Size,
1263 { "Jump-Size", "mrcpv2.Jump-Size",
1264 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1265 },
1266 { &hf_mrcpv2_Kill_On_Barge_In,
1267 { "Kill-On-Barge-In", "mrcpv2.Kill-On-Barge-In",
1268 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1269 },
1270 { &hf_mrcpv2_Lexicon_Search_Order,
1271 { "Lexicon-Search-Order", "mrcpv2.Lexicon-Search-Order",
1272 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1273 },
1274 { &hf_mrcpv2_Load_Lexicon,
1275 { "Load-Lexicon", "mrcpv2.Load-Lexicon",
1276 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1277 },
1278 { &hf_mrcpv2_Logging_Tag,
1279 { "Logging-Tag", "mrcpv2.Logging-Tag",
1280 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1281 },
1282 { &hf_mrcpv2_Max_Time,
1283 { "Max-Time", "mrcpv2.Max-Time",
1284 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1285 },
1286 { &hf_mrcpv2_Media_Type,
1287 { "Media-Type", "mrcpv2.Media-Type",
1288 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1289 },
1290 { &hf_mrcpv2_Min_Verification_Score,
1291 { "Min-Verification-Score", "mrcpv2.Min-Verification-Score",
1292 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1293 },
1294 { &hf_mrcpv2_N_Best_List_Length,
1295 { "N-Best-List-Length", "mrcpv2.N-Best-List-Length",
1296 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1297 },
1298 { &hf_mrcpv2_New_Audio_Channel,
1299 { "New-Audio-Channel", "mrcpv2.New-Audio-Channel",
1300 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1301 },
1302 { &hf_mrcpv2_New_Phrase_ID,
1303 { "New-Phrase-ID", "mrcpv2.New-Phrase-ID",
1304 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1305 },
1306 { &hf_mrcpv2_No_Input_Timeout,
1307 { "No-Input-Timeout", "mrcpv2.No-Input-Timeout",
1308 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1309 },
1310 { &hf_mrcpv2_Num_Max_Verification_Phrases,
1311 { "Num-Max-Verification-Phrases", "mrcpv2.Num-Max-Verification-Phrases",
1312 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1313 },
1314 { &hf_mrcpv2_Num_Min_Consistent_Pronunciations,
1315 { "Num-Min-Consistent-Pronunciations", "mrcpv2.Num-Min-Consistent-Pronunciations",
1316 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1317 },
1318 { &hf_mrcpv2_Num_Min_Verification_Phrases,
1319 { "Num-Min-Verification-Phrases", "mrcpv2.Num-Min-Verification-Phrases",
1320 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1321 },
1322 { &hf_mrcpv2_Personal_Grammar_URI,
1323 { "Personal-Grammar-URI", "mrcpv2.Personal-Grammar-URI",
1324 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1325 },
1326 { &hf_mrcpv2_Phrase_ID,
1327 { "Phrase-ID", "mrcpv2.Phrase-ID",
1328 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1329 },
1330 { &hf_mrcpv2_Phrase_NL,
1331 { "Phrase-NL", "mrcpv2.Phrase-NL",
1332 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1333 },
1334 { &hf_mrcpv2_Prosody_Contour,
1335 { "Prosody-Contour", "mrcpv2.Prosody-Contour",
1336 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1337 },
1338 { &hf_mrcpv2_Prosody_Duration,
1339 { "Prosody-Duration", "mrcpv2.Prosody-Duration",
1340 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1341 },
1342 { &hf_mrcpv2_Prosody_Pitch,
1343 { "Prosody-Pitch", "mrcpv2.Prosody-Pitch",
1344 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1345 },
1346 { &hf_mrcpv2_Prosody_Range,
1347 { "Prosody-Range", "mrcpv2.Prosody-Range",
1348 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1349 },
1350 { &hf_mrcpv2_Prosody_Rate,
1351 { "Prosody-Rate", "mrcpv2.Prosody-Rate",
1352 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1353 },
1354 { &hf_mrcpv2_Prosody_Volume,
1355 { "Prosody-Volume", "mrcpv2.Prosody-Volume",
1356 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1357 },
1358 { &hf_mrcpv2_Proxy_Sync_Id,
1359 { "Proxy-Sync-Id", "mrcpv2.Proxy-Sync-Id",
1360 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1361 },
1362 { &hf_mrcpv2_Recognition_Mode,
1363 { "Recognition-Mode", "mrcpv2.Recognition-Mode",
1364 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1365 },
1366 { &hf_mrcpv2_Recognition_Timeout,
1367 { "Recognition-Timeout", "mrcpv2.Recognition-Timeout",
1368 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1369 },
1370 { &hf_mrcpv2_Recognizer_Context_Block,
1371 { "Recognizer-Context-Block", "mrcpv2.Recognizer-Context-Block",
1372 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1373 },
1374 { &hf_mrcpv2_Record_URI,
1375 { "Record-URI", "mrcpv2.Record-URI",
1376 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1377 },
1378 { &hf_mrcpv2_Repository_URI,
1379 { "Repository-URI", "mrcpv2.Repository-URI",
1380 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1381 },
1382 { &hf_mrcpv2_Save_Best_Waveform,
1383 { "Save-Best-Waveform", "mrcpv2.Save-Best-Waveform",
1384 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1385 },
1386 { &hf_mrcpv2_Save_Waveform,
1387 { "Save-Waveform", "mrcpv2.Save-Waveform",
1388 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1389 },
1390 { &hf_mrcpv2_Sensitivity_Level,
1391 { "Sensitivity-Level", "mrcpv2.Sensitivity-Level",
1392 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1393 },
1394 { &hf_mrcpv2_Set_Cookie,
1395 { "Set-Cookie", "mrcpv2.Set-Cookie",
1396 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1397 },
1398 { &hf_mrcpv2_Speak_Length,
1399 { "Speak-Length", "mrcpv2.Speak-Length",
1400 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1401 },
1402 { &hf_mrcpv2_Speak_Restart,
1403 { "Speak-Restart", "mrcpv2.Speak-Restart",
1404 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1405 },
1406 { &hf_mrcpv2_Speaker_Profile,
1407 { "Speaker-Profile", "mrcpv2.Speaker-Profile",
1408 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1409 },
1410 { &hf_mrcpv2_Speech_Complete_Timeout,
1411 { "Speech-Complete-Timeout", "mrcpv2.Speech-Complete-Timeout",
1412 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1413 },
1414 { &hf_mrcpv2_Speech_Incomplete_Timeout,
1415 { "Speech-Incomplete-Timeout", "mrcpv2.Speech-Incomplete-Timeout",
1416 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1417 },
1418 { &hf_mrcpv2_Speech_Language,
1419 { "Speech-Language", "mrcpv2.Speech-Language",
1420 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1421 },
1422 { &hf_mrcpv2_Speech_Marker,
1423 { "Speech-Marker", "mrcpv2.Speech-Marker",
1424 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1425 },
1426 { &hf_mrcpv2_Speed_Vs_Accuracy,
1427 { "Speed-Vs-Accuracy", "mrcpv2.Speed-Vs-Accuracy",
1428 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1429 },
1430 { &hf_mrcpv2_Start_Input_Timers,
1431 { "Start-Input-Timers", "mrcpv2.Start-Input-Timers",
1432 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1433 },
1434 { &hf_mrcpv2_Trim_Length,
1435 { "Trim-Length", "mrcpv2.Trim-Length",
1436 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1437 },
1438 { &hf_mrcpv2_Vendor_Specific_Parameters,
1439 { "Vendor-Specific-Parameters", "mrcpv2.Vendor-Specific-Parameters",
1440 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1441 },
1442 { &hf_mrcpv2_Ver_Buffer_Utterance,
1443 { "Ver-Buffer-Utterance", "mrcpv2.Ver-Buffer-Utterance",
1444 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1445 },
1446 { &hf_mrcpv2_Verification_Mode,
1447 { "Verification-Mode", "mrcpv2.Verification-Mode",
1448 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1449 },
1450 { &hf_mrcpv2_Voice_Age,
1451 { "Voice-Age", "mrcpv2.Voice-Age",
1452 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1453 },
1454 { &hf_mrcpv2_Voice_Gender,
1455 { "Voice-Gender", "mrcpv2.Voice-Gender",
1456 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1457 },
1458 { &hf_mrcpv2_Voice_Name,
1459 { "Voice-Name", "mrcpv2.Voice-Name",
1460 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1461 },
1462 { &hf_mrcpv2_Voice_Variant,
1463 { "Voice-Variant", "mrcpv2.Voice-Variant",
1464 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1465 },
1466 { &hf_mrcpv2_Voiceprint_Exists,
1467 { "Voiceprint-Exists", "mrcpv2.Voiceprint-Exists",
1468 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1469 },
1470 { &hf_mrcpv2_Voiceprint_Identifier,
1471 { "Voiceprint-Identifier", "mrcpv2.Voiceprint-Identifier",
1472 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1473 },
1474 { &hf_mrcpv2_Waveform_URI,
1475 { "Waveform-URI", "mrcpv2.Waveform-URI",
1476 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1477 },
1478 { &hf_mrcpv2_Weight,
1479 { "Weight", "mrcpv2.Weight",
1480 FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL },
1481 }
1482 };
1483
1484 static ei_register_info ei[] = {
1485 { &ei_mrcpv2_Content_Length_invalid, { "mrcpv2.Content-Length.invalid", PI_MALFORMED, PI_ERROR,
1486 "Content Length must be a string containing an integer", EXPFILL }}
1487 };
1488
1489 static gint *ett[] = {
1490 &ett_mrcpv2,
1491 &ett_Request_Line,
1492 &ett_Response_Line,
1493 &ett_Event_Line,
1494 &ett_Status_Code
1495 };
1496
1497 proto_mrcpv2 = proto_register_protocol("Media Resource Control Protocol Version 2 (MRCPv2)", "MRCPv2", "mrcpv2");
1498
1499 proto_register_field_array(proto_mrcpv2, hf, array_length(hf));
1500 proto_register_subtree_array(ett, array_length(ett));
1501
1502 expert_mrcpv2 = expert_register_protocol(proto_mrcpv2);
1503 expert_register_field_array(expert_mrcpv2, ei, array_length(ei));
1504 }
1505
1506 void
proto_reg_handoff_mrcpv2(void)1507 proto_reg_handoff_mrcpv2(void)
1508 {
1509 dissector_handle_t mrcpv2_handle;
1510
1511 mrcpv2_handle = create_dissector_handle(dissect_mrcpv2_tcp, proto_mrcpv2);
1512
1513 dissector_add_uint_range_with_preference ("tcp.port", TCP_DEFAULT_RANGE, mrcpv2_handle);
1514 }
1515 /*
1516 * Editor modelines
1517 *
1518 * Local Variables:
1519 * c-basic-offset: 4
1520 * tab-width: 8
1521 * indent-tabs-mode: nil
1522 * End:
1523 *
1524 * ex: set shiftwidth=4 tabstop=8 expandtab:
1525 * :indentSize=4:tabSize=8:noTabs=true:
1526 */
1527