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