2010-02-07 14:30:11 +00:00
|
|
|
/* packet-applemidi.c
|
|
|
|
* Routines for dissection of Apple network-midi session establishment.
|
2012-02-27 09:18:53 +00:00
|
|
|
* Copyright 2006-2012, Tobias Erichsen <t.erichsen@gmx.de>
|
2010-02-07 14:30:11 +00:00
|
|
|
*
|
|
|
|
* Wireshark - Network traffic analyzer
|
|
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* Copied from packet-data.c, README.developer, and various other files.
|
|
|
|
*
|
2018-02-12 11:23:27 +00:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
2010-02-07 14:30:11 +00:00
|
|
|
*
|
|
|
|
*
|
2012-02-27 09:18:53 +00:00
|
|
|
* Apple network-midi session establishment is a lightweight protocol for
|
|
|
|
* providing a simple session establishment for MIDI-data sent in the form
|
|
|
|
* of RTP-MIDI (RFC 4695 / 6295). Peers recognize each other using the
|
|
|
|
* Apple Bonjour scheme with the service-name "_apple-midi._udp", establish
|
|
|
|
* a connection using AppleMIDI (no official name, just an abbreviation)
|
|
|
|
* and then send payload using RTP-MIDI. The implementation of this
|
|
|
|
* dissector is based on the Apple implementation summary from May 6th, 2005
|
|
|
|
* and the extension from August 13th, 2010.
|
|
|
|
*
|
|
|
|
* 2010-11-29
|
|
|
|
* - initial version of dissector
|
|
|
|
* 2012-02-24
|
|
|
|
* - implemented dynamic payloadtype support to automatically punt
|
|
|
|
* the decoding to the RTP-MIDI dissector via the RTP dissector
|
|
|
|
* - added new bitrate receive limit feature
|
2010-02-07 14:30:11 +00:00
|
|
|
*
|
|
|
|
* Here are some links:
|
|
|
|
*
|
|
|
|
* http://www.cs.berkeley.edu/~lazzaro/rtpmidi/
|
|
|
|
* http://www.faqs.org/rfcs/rfc4695.html
|
2012-02-27 09:18:53 +00:00
|
|
|
* http://www.faqs.org/rfcs/rfc6295.html
|
2010-02-07 14:30:11 +00:00
|
|
|
*/
|
|
|
|
|
2012-09-20 02:03:38 +00:00
|
|
|
#include "config.h"
|
2010-02-07 14:30:11 +00:00
|
|
|
|
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/conversation.h>
|
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
#include "packet-rtp.h"
|
|
|
|
|
2013-03-12 23:09:37 +00:00
|
|
|
void proto_register_applemidi(void);
|
|
|
|
void proto_reg_handoff_applemidi(void);
|
|
|
|
|
2010-02-07 14:30:11 +00:00
|
|
|
/* Definitions for protocol name during dissector-register */
|
|
|
|
#define APPLEMIDI_DISSECTOR_NAME "Apple Network-MIDI Session Protocol"
|
2012-02-27 09:18:53 +00:00
|
|
|
#define APPLEMIDI_DISSECTOR_SHORTNAME "AppleMIDI"
|
|
|
|
#define APPLEMIDI_DISSECTOR_ABBREVIATION "applemidi"
|
2010-02-07 14:30:11 +00:00
|
|
|
|
|
|
|
/* Signature "Magic Value" for Apple network MIDI session establishment */
|
|
|
|
#define APPLEMIDI_PROTOCOL_SIGNATURE 0xffff
|
|
|
|
|
|
|
|
/* Apple network MIDI valid commands */
|
|
|
|
#define APPLEMIDI_COMMAND_INVITATION 0x494e /* "IN" */
|
2012-02-27 09:18:53 +00:00
|
|
|
#define APPLEMIDI_COMMAND_INVITATION_REJECTED 0x4e4f /* "NO" */
|
|
|
|
#define APLLEMIDI_COMMAND_INVITATION_ACCEPTED 0x4f4b /* "OK" */
|
2010-02-07 14:30:11 +00:00
|
|
|
#define APPLEMIDI_COMMAND_ENDSESSION 0x4259 /* "BY" */
|
|
|
|
#define APPLEMIDI_COMMAND_SYNCHRONIZATION 0x434b /* "CK" */
|
|
|
|
#define APPLEMIDI_COMMAND_RECEIVER_FEEDBACK 0x5253 /* "RS" */
|
2012-02-27 09:18:53 +00:00
|
|
|
#define APPLEMIDI_COMMAND_BITRATE_RECEIVE_LIMIT 0x524c /* "RL" */
|
2010-02-07 14:30:11 +00:00
|
|
|
|
|
|
|
static int hf_applemidi_signature = -1;
|
|
|
|
static int hf_applemidi_command = -1;
|
|
|
|
static int hf_applemidi_protocol_version = -1;
|
|
|
|
static int hf_applemidi_token = -1;
|
|
|
|
static int hf_applemidi_ssrc = -1;
|
|
|
|
static int hf_applemidi_name = -1;
|
|
|
|
static int hf_applemidi_count = -1;
|
|
|
|
static int hf_applemidi_padding = -1;
|
|
|
|
static int hf_applemidi_timestamp1 = -1;
|
|
|
|
static int hf_applemidi_timestamp2 = -1;
|
|
|
|
static int hf_applemidi_timestamp3 = -1;
|
|
|
|
static int hf_applemidi_sequence_num = -1;
|
|
|
|
static int hf_applemidi_rtp_sequence_num = -1;
|
2012-02-27 09:18:53 +00:00
|
|
|
static int hf_applemidi_rtp_bitrate_limit = -1;
|
|
|
|
static int hf_applemidi_unknown_data = -1;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
static gint ett_applemidi = -1;
|
|
|
|
static gint ett_applemidi_seq_num = -1;
|
|
|
|
|
|
|
|
|
|
|
|
static const value_string applemidi_commands[] = {
|
2012-02-27 09:18:53 +00:00
|
|
|
{ APPLEMIDI_COMMAND_INVITATION, "Invitation" },
|
2010-02-07 14:30:11 +00:00
|
|
|
{ APPLEMIDI_COMMAND_INVITATION_REJECTED, "Invitation Rejected" },
|
|
|
|
{ APLLEMIDI_COMMAND_INVITATION_ACCEPTED, "Invitation Accepted" },
|
2012-02-27 09:18:53 +00:00
|
|
|
{ APPLEMIDI_COMMAND_ENDSESSION, "End Session" },
|
2010-02-07 14:30:11 +00:00
|
|
|
{ APPLEMIDI_COMMAND_SYNCHRONIZATION, "Synchronization" },
|
|
|
|
{ APPLEMIDI_COMMAND_RECEIVER_FEEDBACK, "Receiver Feedback" },
|
2012-02-27 09:18:53 +00:00
|
|
|
{ APPLEMIDI_COMMAND_BITRATE_RECEIVE_LIMIT, "Bitrate Receive Limit" },
|
2010-02-07 14:30:11 +00:00
|
|
|
{ 0, NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
static int proto_applemidi = -1;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2010-02-07 23:51:56 +00:00
|
|
|
static dissector_handle_t applemidi_handle;
|
|
|
|
static dissector_handle_t rtp_handle;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
static const char applemidi_unknown_command[] = "unknown command: 0x%04x";
|
|
|
|
|
2010-02-07 14:30:11 +00:00
|
|
|
static void
|
2010-02-07 23:51:56 +00:00
|
|
|
dissect_applemidi_common( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint16 command ) {
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_item *ti;
|
2010-02-07 14:30:11 +00:00
|
|
|
guint16 seq_num;
|
|
|
|
guint8 count;
|
|
|
|
guint8 *name;
|
2012-02-27 09:18:53 +00:00
|
|
|
gint offset = 0;
|
|
|
|
gint len;
|
|
|
|
gint string_size;
|
2010-02-07 23:51:56 +00:00
|
|
|
proto_tree *applemidi_tree;
|
|
|
|
proto_tree *applemidi_tree_seq_num;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
col_set_str( pinfo->cinfo, COL_PROTOCOL, APPLEMIDI_DISSECTOR_SHORTNAME );
|
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
col_add_fstr( pinfo->cinfo, COL_INFO, "%s", val_to_str( command, applemidi_commands, applemidi_unknown_command ) );
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
ti = proto_tree_add_item( tree, proto_applemidi, tvb, 0, -1, ENC_NA );
|
|
|
|
applemidi_tree = proto_item_add_subtree( ti, ett_applemidi );
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_signature, tvb, offset, 2, ENC_BIG_ENDIAN );
|
|
|
|
offset += 2;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_command, tvb, offset, 2, ENC_BIG_ENDIAN );
|
|
|
|
offset += 2;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
/* the format of packets for "IN", "NO", "OK" and "BY" is identical and contains
|
|
|
|
* the protocol version, a random number generated by the initiator of the session,
|
|
|
|
* the SSRC that is used by the respective sides RTP-entity and optionally the
|
|
|
|
* name of the participant */
|
|
|
|
if ( ( APPLEMIDI_COMMAND_INVITATION == command ) ||
|
|
|
|
( APPLEMIDI_COMMAND_INVITATION_REJECTED == command ) ||
|
|
|
|
( APLLEMIDI_COMMAND_INVITATION_ACCEPTED == command ) ||
|
|
|
|
( APPLEMIDI_COMMAND_ENDSESSION == command ) ) {
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_protocol_version, tvb, offset, 4, ENC_BIG_ENDIAN );
|
|
|
|
offset += 4;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_token, tvb, offset, 4, ENC_BIG_ENDIAN );
|
|
|
|
offset += 4;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN );
|
|
|
|
offset += 4;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
len = tvb_reported_length(tvb) - offset;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
/* Name is optional */
|
|
|
|
if ( len > 0 ) {
|
|
|
|
name = tvb_get_string_enc( wmem_packet_scope(), tvb, offset, len, ENC_UTF_8|ENC_NA );
|
|
|
|
string_size = (gint)( strlen( name ) + 1 );
|
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_name, tvb, offset, string_size, ENC_UTF_8|ENC_NA );
|
|
|
|
col_append_fstr( pinfo->cinfo, COL_INFO, ": peer = \"%s\"", name );
|
|
|
|
offset += string_size;
|
|
|
|
}
|
2010-02-07 14:30:11 +00:00
|
|
|
|
|
|
|
/* the synchronization packet contains three 64bit timestamps, and a value to define how
|
|
|
|
* many of the timestamps transmitted are valid */
|
2015-01-30 18:49:59 +00:00
|
|
|
} else if ( APPLEMIDI_COMMAND_SYNCHRONIZATION == command ) {
|
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN );
|
|
|
|
offset += 4;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
count = tvb_get_guint8( tvb, offset );
|
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_count, tvb, offset, 1, ENC_BIG_ENDIAN );
|
|
|
|
col_append_fstr( pinfo->cinfo, COL_INFO, ": count = %u", count );
|
|
|
|
offset += 1;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_padding, tvb, offset, 3, ENC_BIG_ENDIAN );
|
|
|
|
offset += 3;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp1, tvb, offset, 8, ENC_BIG_ENDIAN );
|
|
|
|
offset += 8;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp2, tvb, offset, 8, ENC_BIG_ENDIAN );
|
|
|
|
offset += 8;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_timestamp3, tvb, offset, 8, ENC_BIG_ENDIAN );
|
|
|
|
offset += 8;
|
2010-02-07 14:30:11 +00:00
|
|
|
/* With the receiver feedback packet, the recipient can tell the sender up to what sequence
|
2010-02-07 23:51:56 +00:00
|
|
|
* number in the RTP-stream the packets have been received; this can be used to shorten the
|
2010-02-07 14:30:11 +00:00
|
|
|
* recovery-journal-section in the RTP-session */
|
2015-01-30 18:49:59 +00:00
|
|
|
} else if ( APPLEMIDI_COMMAND_RECEIVER_FEEDBACK == command ) {
|
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN );
|
|
|
|
offset += 4;
|
|
|
|
|
|
|
|
ti = proto_tree_add_item( applemidi_tree, hf_applemidi_sequence_num, tvb, offset, 4, ENC_BIG_ENDIAN );
|
|
|
|
/* Apple includes a 32bit sequence-number, but the RTP-packet only specifies 16bit.
|
|
|
|
* this subtree and subitem are added to be able to associate the sequence-number
|
|
|
|
* here easier with the one specified in the corresponding RTP-packet */
|
|
|
|
applemidi_tree_seq_num = proto_item_add_subtree( ti, ett_applemidi_seq_num );
|
|
|
|
seq_num = tvb_get_ntohs( tvb, offset );
|
|
|
|
proto_tree_add_uint( applemidi_tree_seq_num, hf_applemidi_rtp_sequence_num, tvb, offset, 2, seq_num );
|
|
|
|
offset += 4;
|
|
|
|
|
|
|
|
col_append_fstr( pinfo->cinfo, COL_INFO, ": seq = %u", seq_num );
|
2012-02-27 09:18:53 +00:00
|
|
|
/* With the bitrate receive limit packet, the recipient can tell the sender to limit
|
|
|
|
the transmission to a certain bitrate. This is important if the peer is a gateway
|
|
|
|
to a hardware-device that only supports a certain speed. Like the MIDI 1.0 DIN-cable
|
|
|
|
MIDI-implementation which is limited to 31250. */
|
2015-01-30 18:49:59 +00:00
|
|
|
} else if ( APPLEMIDI_COMMAND_BITRATE_RECEIVE_LIMIT == command ) {
|
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_ssrc, tvb, offset, 4, ENC_BIG_ENDIAN );
|
|
|
|
offset += 4;
|
2012-02-27 09:18:53 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_rtp_bitrate_limit,
|
|
|
|
tvb, offset, 4, ENC_BIG_ENDIAN );
|
|
|
|
offset += 4;
|
|
|
|
}
|
|
|
|
/* If there is any remaining data (possibly because an unknown command was encountered),
|
|
|
|
* we just dump it here */
|
|
|
|
len = tvb_reported_length_remaining( tvb, offset );
|
|
|
|
if ( len > 0 ) {
|
|
|
|
proto_tree_add_item( applemidi_tree, hf_applemidi_unknown_data, tvb, offset, len, ENC_NA );
|
2010-02-07 14:30:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2012-02-27 09:18:53 +00:00
|
|
|
test_applemidi(tvbuff_t *tvb, guint16 *command_p, gboolean conversation_established ) {
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2010-02-07 23:51:56 +00:00
|
|
|
*command_p = 0xffff;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2010-02-07 23:51:56 +00:00
|
|
|
/* An applemidi session protocol UDP-packet must start with the "magic value" of 0xffff ... */
|
|
|
|
if ( APPLEMIDI_PROTOCOL_SIGNATURE != tvb_get_ntohs( tvb, 0 ) )
|
|
|
|
return FALSE;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2010-02-07 23:51:56 +00:00
|
|
|
*command_p = tvb_get_ntohs( tvb, 2 );
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
/* If the conversation is establised (one prior packet with a valid known command)
|
|
|
|
* we won't check the commands anymore - this way we still show new commands
|
2016-01-06 00:58:42 +00:00
|
|
|
* Apple might introduce as "unknown" instead of punting to RTP-dissector */
|
2012-02-27 09:18:53 +00:00
|
|
|
if ( conversation_established ) {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ... followed by packet-command: "IN", "NO", "OK", "BY", "CK" and "RS" and "RL" */
|
|
|
|
if ( ( APPLEMIDI_COMMAND_INVITATION == *command_p ) ||
|
|
|
|
( APPLEMIDI_COMMAND_INVITATION_REJECTED == *command_p ) ||
|
|
|
|
( APLLEMIDI_COMMAND_INVITATION_ACCEPTED == *command_p ) ||
|
|
|
|
( APPLEMIDI_COMMAND_ENDSESSION == *command_p ) ||
|
|
|
|
( APPLEMIDI_COMMAND_SYNCHRONIZATION == *command_p ) ||
|
|
|
|
( APPLEMIDI_COMMAND_RECEIVER_FEEDBACK == *command_p ) ||
|
|
|
|
( APPLEMIDI_COMMAND_BITRATE_RECEIVE_LIMIT == *command_p ) )
|
2010-02-07 23:51:56 +00:00
|
|
|
return TRUE;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2010-02-07 23:51:56 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
2010-02-07 14:30:11 +00:00
|
|
|
|
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
|
2010-02-07 23:51:56 +00:00
|
|
|
/* dissect_applemidi() is called when a packet is seen from a previously identified applemidi conversation */
|
|
|
|
/* If the packet isn't a valid applemidi packet, assume it's an RTP-MIDI packet. */
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2015-11-15 13:00:10 +00:00
|
|
|
static int
|
|
|
|
dissect_applemidi( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ ) {
|
2010-02-07 23:51:56 +00:00
|
|
|
guint16 command;
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
if ( test_applemidi( tvb, &command, TRUE ) )
|
2010-02-07 23:51:56 +00:00
|
|
|
dissect_applemidi_common( tvb, pinfo, tree, command );
|
|
|
|
else
|
|
|
|
call_dissector( rtp_handle, tvb, pinfo, tree );
|
2015-11-15 13:00:10 +00:00
|
|
|
|
|
|
|
return tvb_captured_length(tvb);
|
2010-02-07 23:51:56 +00:00
|
|
|
}
|
2010-02-07 14:30:11 +00:00
|
|
|
|
2010-02-07 23:51:56 +00:00
|
|
|
static gboolean
|
2012-09-10 21:40:21 +00:00
|
|
|
dissect_applemidi_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ ) {
|
2010-02-07 23:51:56 +00:00
|
|
|
|
|
|
|
guint16 command;
|
|
|
|
conversation_t *p_conv;
|
2015-01-30 18:49:59 +00:00
|
|
|
rtp_dyn_payload_t *rtp_dyn_payload;
|
2010-02-07 23:51:56 +00:00
|
|
|
|
2015-01-30 18:49:59 +00:00
|
|
|
if ( tvb_captured_length( tvb ) < 4)
|
2010-02-07 23:51:56 +00:00
|
|
|
return FALSE; /* not enough bytes to check */
|
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
if ( !test_applemidi( tvb, &command, FALSE ) ) {
|
2010-02-07 23:51:56 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
/* set dynamic payload-type 97 which is used by Apple for their RTP-MIDI implementation for this
|
|
|
|
address/port-tuple to cause RTP-dissector to call the RTP-MIDI-dissector for payload-decoding */
|
|
|
|
|
2014-04-02 06:07:16 +00:00
|
|
|
rtp_dyn_payload = rtp_dyn_payload_new();
|
|
|
|
rtp_dyn_payload_insert(rtp_dyn_payload, 97, "rtp-midi", 10000);
|
2016-12-14 21:55:05 +00:00
|
|
|
rtp_add_address( pinfo, PT_UDP, &pinfo->src, pinfo->srcport, 0, APPLEMIDI_DISSECTOR_SHORTNAME,
|
2016-01-24 03:40:51 +00:00
|
|
|
pinfo->num, FALSE, rtp_dyn_payload);
|
2012-02-27 09:18:53 +00:00
|
|
|
|
|
|
|
/* call dissect_applemidi() from now on for UDP packets on this "connection"
|
|
|
|
it is important to do this step after calling rtp_add_address, otherwise
|
|
|
|
all further packets will go directly to the RTP-dissector! */
|
|
|
|
|
2010-05-13 18:28:34 +00:00
|
|
|
p_conv = find_or_create_conversation(pinfo);
|
2010-02-07 23:51:56 +00:00
|
|
|
conversation_set_dissector( p_conv, applemidi_handle );
|
|
|
|
|
2012-02-27 09:18:53 +00:00
|
|
|
/* punt to actual decoding */
|
|
|
|
|
2010-02-07 23:51:56 +00:00
|
|
|
dissect_applemidi_common( tvb, pinfo, tree, command );
|
|
|
|
return TRUE;
|
|
|
|
|
2010-02-07 14:30:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_applemidi( void )
|
|
|
|
{
|
|
|
|
static hf_register_info hf[] = {
|
|
|
|
{
|
|
|
|
&hf_applemidi_signature,
|
|
|
|
{
|
|
|
|
"Signature",
|
|
|
|
"applemidi.signature",
|
|
|
|
FT_UINT16,
|
|
|
|
BASE_HEX,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_command,
|
|
|
|
{
|
|
|
|
"Command",
|
|
|
|
"applemidi.command",
|
|
|
|
FT_UINT16,
|
|
|
|
BASE_HEX,
|
|
|
|
VALS( applemidi_commands ),
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_protocol_version,
|
|
|
|
{
|
|
|
|
"Protocol Version",
|
|
|
|
"applemidi.protocol_version",
|
|
|
|
FT_UINT32,
|
|
|
|
BASE_DEC,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_token,
|
|
|
|
{
|
|
|
|
"Initiator Token",
|
|
|
|
"applemidi.initiator_token",
|
|
|
|
FT_UINT32,
|
|
|
|
BASE_HEX,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_ssrc,
|
|
|
|
{
|
|
|
|
"Sender SSRC",
|
|
|
|
"applemidi.sender_ssrc",
|
|
|
|
FT_UINT32,
|
|
|
|
BASE_HEX,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_name,
|
|
|
|
{
|
|
|
|
"Name",
|
|
|
|
"applemidi.name",
|
|
|
|
FT_STRING,
|
|
|
|
BASE_NONE,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_count,
|
|
|
|
{
|
|
|
|
"Count",
|
|
|
|
"applemidi.count",
|
|
|
|
FT_UINT8,
|
|
|
|
BASE_DEC,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_padding,
|
|
|
|
{
|
|
|
|
"Padding",
|
|
|
|
"applemidi.padding",
|
|
|
|
FT_UINT24,
|
|
|
|
BASE_HEX,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_timestamp1,
|
|
|
|
{
|
|
|
|
"Timestamp 1",
|
|
|
|
"applemidi.timestamp1",
|
|
|
|
FT_UINT64,
|
|
|
|
BASE_HEX,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_timestamp2,
|
|
|
|
{
|
|
|
|
"Timestamp 2",
|
|
|
|
"applemidi.timestamp2",
|
|
|
|
FT_UINT64,
|
|
|
|
BASE_HEX,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_timestamp3,
|
|
|
|
{
|
|
|
|
"Timestamp 3",
|
|
|
|
"applemidi.timestamp3",
|
|
|
|
FT_UINT64,
|
|
|
|
BASE_HEX,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_sequence_num,
|
|
|
|
{
|
|
|
|
"Sequence Number",
|
|
|
|
"applemidi.sequence_number",
|
|
|
|
FT_UINT32,
|
|
|
|
BASE_HEX,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_rtp_sequence_num,
|
|
|
|
{
|
|
|
|
"RTP Sequence Number",
|
|
|
|
"applemidi.rtp_sequence_number",
|
|
|
|
FT_UINT16,
|
|
|
|
BASE_DEC,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
2012-02-27 09:18:53 +00:00
|
|
|
{
|
|
|
|
&hf_applemidi_rtp_bitrate_limit,
|
|
|
|
{
|
|
|
|
"Bitrate limit",
|
|
|
|
"applemidi.bitrate_limit",
|
|
|
|
FT_UINT32,
|
|
|
|
BASE_DEC,
|
|
|
|
NULL,
|
|
|
|
0x0,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&hf_applemidi_unknown_data,
|
|
|
|
{
|
|
|
|
"Unknown Data",
|
2012-07-22 03:06:37 +00:00
|
|
|
"applemidi.unknown_data",
|
2012-02-27 09:18:53 +00:00
|
|
|
FT_BYTES,
|
|
|
|
BASE_NONE,
|
|
|
|
NULL,
|
|
|
|
0x00,
|
|
|
|
NULL, HFILL
|
|
|
|
}
|
|
|
|
},
|
2010-02-07 14:30:11 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_applemidi,
|
|
|
|
&ett_applemidi_seq_num
|
|
|
|
};
|
|
|
|
|
2012-04-23 17:50:02 +00:00
|
|
|
proto_applemidi = proto_register_protocol( APPLEMIDI_DISSECTOR_NAME,
|
|
|
|
APPLEMIDI_DISSECTOR_SHORTNAME,
|
|
|
|
APPLEMIDI_DISSECTOR_ABBREVIATION );
|
2010-02-07 14:30:11 +00:00
|
|
|
proto_register_field_array( proto_applemidi, hf, array_length( hf ) );
|
|
|
|
proto_register_subtree_array( ett, array_length( ett ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_applemidi( void ) {
|
|
|
|
|
|
|
|
|
2015-12-09 03:49:44 +00:00
|
|
|
applemidi_handle = create_dissector_handle( dissect_applemidi, proto_applemidi );
|
2010-02-07 14:30:11 +00:00
|
|
|
|
|
|
|
/* If we cannot decode the data it will be RTP-MIDI since the Apple session protocol uses
|
|
|
|
* two ports: the control-port and the MIDI-port. On both ports an invitation is being sent.
|
|
|
|
* The second port is then used for the RTP-MIDI-data. So if we can't find valid AppleMidi
|
|
|
|
* packets, it will be most likely RTP-MIDI...
|
|
|
|
*/
|
2016-03-16 13:02:52 +00:00
|
|
|
rtp_handle = find_dissector_add_dependency( "rtp", proto_applemidi );
|
2015-07-13 00:40:31 +00:00
|
|
|
heur_dissector_add( "udp", dissect_applemidi_heur, "Apple MIDI over UDP", "applemidi_udp", proto_applemidi, HEURISTIC_ENABLE );
|
2010-02-07 14:30:11 +00:00
|
|
|
}
|
2014-10-03 14:13:07 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Editor modelines - http://www.wireshark.org/tools/modelines.html
|
|
|
|
*
|
|
|
|
* Local variables:
|
|
|
|
* c-basic-offset: 8
|
|
|
|
* tab-width: 8
|
|
|
|
* indent-tabs-mode: t
|
|
|
|
* End:
|
|
|
|
*
|
|
|
|
* vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
|
|
|
* :indentSize=8:tabSize=8:noTabs=false:
|
|
|
|
*/
|