/* nopad == TRUE : Do not add any padding before this string * exactlen == TRUE : len contains the exact len of the string in bytes. * bc: pointer to variable with amount of data left in the byte parameters * region */ const gchar * get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp, gboolean useunicode, int *len, gboolean nopad, gboolean exactlen, guint16 *bcp) { gchar *cur; const gchar *string; int string_len = 0; int copylen; gboolean overflow = FALSE; if (*bcp == 0) { /* Not enough data in buffer */ return NULL; } if (useunicode) { if ((!nopad) && (*offsetp % 2)) { (*offsetp)++; /* Looks like a pad byte there sometimes */ (*bcp)--; if (*bcp == 0) { /* Not enough data in buffer */ return NULL; } } if(exactlen){ string_len = *len; if (string_len < 0) { /* This probably means it's a very large unsigned number; just set it to the largest signed number, so that we throw the appropriate exception. */ string_len = INT_MAX; } } string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp); } else { if(exactlen){ /* * The string we return must be null-terminated. */ cur=ep_alloc(MAX_UNICODE_STR_LEN+3+1); copylen = *len; if (copylen < 0) { /* This probably means it's a very large unsigned number; just set it to the largest signed number, so that we throw the appropriate exception. */ copylen = INT_MAX; } tvb_ensure_bytes_exist(tvb, *offsetp, copylen); if (copylen > MAX_UNICODE_STR_LEN) { copylen = MAX_UNICODE_STR_LEN; overflow = TRUE; } tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen); cur[copylen] = '\0'; if (overflow) g_strlcat(cur, "...",MAX_UNICODE_STR_LEN+3+1); string_len = *len; string = cur; } else { string = tvb_get_const_stringz(tvb, *offsetp, &string_len); } } *len = string_len; return string; }
/* Dissect OSC message */ static int dissect_osc_message(tvbuff_t *tvb, proto_item *ti, proto_tree *osc_tree, gint offset, gint len) { proto_tree *message_tree; proto_tree *header_tree; gint slen; gint rem; gint end = offset + len; const gchar *path; gint path_len; gint path_offset; const gchar *format; gint format_offset; gint format_len; const gchar *ptr; /* peek/read path */ path_offset = offset; path = tvb_get_const_stringz(tvb, path_offset, &path_len); if( (rem = path_len%4) ) path_len += 4-rem; if(!is_valid_path(path)) return -1; /* peek/read fmt */ format_offset = path_offset + path_len; format = tvb_get_const_stringz(tvb, format_offset, &format_len); if( (rem = format_len%4) ) format_len += 4-rem; if(!is_valid_format(format)) return -1; /* create message */ ti = proto_tree_add_none_format(osc_tree, hf_osc_message_type, tvb, offset, len, "Message: %s %s", path, format); message_tree = proto_item_add_subtree(ti, ett_osc_message); /* append header */ ti = proto_tree_add_item(message_tree, hf_osc_message_header_type, tvb, offset, path_len+format_len, ENC_NA); header_tree = proto_item_add_subtree(ti, ett_osc_message_header); /* append path */ proto_tree_add_item(header_tree, hf_osc_message_path_type, tvb, path_offset, path_len, ENC_ASCII | ENC_NA); /* append format */ proto_tree_add_item(header_tree, hf_osc_message_format_type, tvb, format_offset, format_len, ENC_ASCII | ENC_NA); offset += path_len + format_len; /* ::parse argument:: */ ptr = format + 1; /* skip ',' */ while( (*ptr != '\0') && (offset < end) ) { switch(*ptr) { case OSC_INT32: proto_tree_add_item(message_tree, hf_osc_message_int32_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case OSC_FLOAT: proto_tree_add_item(message_tree, hf_osc_message_float_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case OSC_STRING: slen = tvb_strsize(tvb, offset); if( (rem = slen%4) ) slen += 4-rem; proto_tree_add_item(message_tree, hf_osc_message_string_type, tvb, offset, slen, ENC_ASCII | ENC_NA); offset += slen; break; case OSC_BLOB: { proto_item *bi; proto_tree *blob_tree; gint32 blen = tvb_get_ntohl(tvb, offset); slen = blen; if( (rem = slen%4) ) slen += 4-rem; bi = proto_tree_add_none_format(message_tree, hf_osc_message_blob_type, tvb, offset, 4+slen, "Blob: %i bytes", blen); blob_tree = proto_item_add_subtree(bi, ett_osc_blob); proto_tree_add_int_format_value(blob_tree, hf_osc_message_blob_size_type, tvb, offset, 4, blen, "%i bytes", blen); offset += 4; /* check for zero length blob */ if(blen == 0) break; proto_tree_add_item(blob_tree, hf_osc_message_blob_data_type, tvb, offset, slen, ENC_NA); offset += slen; break; } case OSC_TRUE: proto_tree_add_item(message_tree, hf_osc_message_true_type, tvb, offset, 0, ENC_NA); break; case OSC_FALSE: proto_tree_add_item(message_tree, hf_osc_message_false_type, tvb, offset, 0, ENC_NA); break; case OSC_NIL: proto_tree_add_item(message_tree, hf_osc_message_nil_type, tvb, offset, 0, ENC_NA); break; case OSC_BANG: proto_tree_add_item(message_tree, hf_osc_message_bang_type, tvb, offset, 0, ENC_NA); break; case OSC_INT64: proto_tree_add_item(message_tree, hf_osc_message_int64_type, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; break; case OSC_DOUBLE: proto_tree_add_item(message_tree, hf_osc_message_double_type, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; break; case OSC_TIMETAG: { guint32 sec = tvb_get_ntohl(tvb, offset); guint32 frac = tvb_get_ntohl(tvb, offset+4); nstime_t ns; if( (sec == 0) && (frac == 1) ) proto_tree_add_time_format_value(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, &ns, immediate_fmt, immediate_str); else proto_tree_add_item(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN); offset += 8; } break; case OSC_SYMBOL: slen = tvb_strsize(tvb, offset); if( (rem = slen%4) ) slen += 4-rem; proto_tree_add_item(message_tree, hf_osc_message_symbol_type, tvb, offset, slen, ENC_ASCII | ENC_NA); offset += slen; break; case OSC_CHAR: offset += 3; proto_tree_add_item(message_tree, hf_osc_message_char_type, tvb, offset, 1, ENC_ASCII | ENC_NA); offset += 1; break; case OSC_RGBA: { proto_item *ri; proto_tree *rgba_tree; ri = proto_tree_add_item(message_tree, hf_osc_message_rgba_type, tvb, offset, 4, ENC_BIG_ENDIAN); rgba_tree = proto_item_add_subtree(ri, ett_osc_rgba); proto_tree_add_item(rgba_tree, hf_osc_message_rgba_red_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_green_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_blue_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_alpha_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case OSC_MIDI: { const gchar *status_str; proto_item *mi = NULL; proto_tree *midi_tree; guint8 port; guint8 command; guint8 data1; guint8 data2; guint8 status; guint8 channel; gboolean system_msg; guint8 status_shifted; port = tvb_get_guint8(tvb, offset); command = tvb_get_guint8(tvb, offset+1); data1 = tvb_get_guint8(tvb, offset+2); data2 = tvb_get_guint8(tvb, offset+3); status = command & 0xF0; channel = command & 0x0F; system_msg = status == 0xF0; /* is system message */ status_shifted = status >> 4; if(system_msg) status_str = val_to_str_ext_const(command, &MIDI_system_ext, "Unknown"); else status_str = val_to_str_ext_const(status_shifted, &MIDI_status_ext, "Unknown"); if(system_msg) { mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, %s, %i, %i", port, status_str, data1, data2); } else { switch(status_shifted) { case MIDI_STATUS_NOTE_ON: case MIDI_STATUS_NOTE_OFF: case MIDI_STATUS_NOTE_PRESSURE: { const gchar *note_str; note_str = val_to_str_ext_const(data1, &MIDI_note_ext, "Unknown"); mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, Channel %i, %s, %s, %i", port, channel, status_str, note_str, data2); break; } case MIDI_STATUS_CONTROLLER: { const gchar *control_str; control_str = val_to_str_ext_const(data1, &MIDI_control_ext, "Unknown"); mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, Channel %i, %s, %s, %i", port, channel, status_str, control_str, data2); break; } case MIDI_STATUS_PITCH_BENDER: { const gint bender = (((gint)data2 << 7) | (gint)data1) - 0x2000; mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, Channel %i, %s, %i", port, channel, status_str, bender); break; } default: { mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Port %i, Channel %i, %s, %i, %i", port, channel, status_str, data1, data2); break; } } } midi_tree = proto_item_add_subtree(mi, ett_osc_midi); proto_tree_add_item(midi_tree, hf_osc_message_midi_port_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if(system_msg) { proto_tree_add_item(midi_tree, hf_osc_message_midi_system_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } else { proto_tree_add_item(midi_tree, hf_osc_message_midi_status_type, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(midi_tree, hf_osc_message_midi_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; switch(status_shifted) { case MIDI_STATUS_NOTE_ON: case MIDI_STATUS_NOTE_OFF: { proto_tree_add_item(midi_tree, hf_osc_message_midi_note_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_velocity_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case MIDI_STATUS_NOTE_PRESSURE: { proto_tree_add_item(midi_tree, hf_osc_message_midi_note_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_pressure_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case MIDI_STATUS_CONTROLLER: { proto_tree_add_item(midi_tree, hf_osc_message_midi_controller_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case MIDI_STATUS_CHANNEL_PRESSURE: { proto_tree_add_item(midi_tree, hf_osc_message_midi_pressure_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case MIDI_STATUS_PITCH_BENDER: { const gint bender = (((gint)data2 << 7) | (gint)data1) - 0x2000; proto_tree_add_int(midi_tree, hf_osc_message_midi_bender_type, tvb, offset, 2, bender); offset += 2; break; } default: { proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } } } break; } default: /* if we get here, there must be a bug in the dissector */ DISSECTOR_ASSERT_NOT_REACHED(); break; } ptr++; } if(offset != end) return -1; else return 0; }
/* * It appears that browser announcements sent to \MAILSLOT\LANMAN aren't * the same as browser announcements sent to \MAILSLOT\BROWSE. * Was that an older version of the protocol? * * The document at * * http://www.samba.org/samba/ftp/specs/brow_rev.txt * * gives both formats of host announcement packets, saying that * "[The first] format seems wrong", that one being what appears to * show up in \MAILSLOT\LANMAN packets, and that "[The second one] * may be better", that one being what appears to show up in * \MAILSLOT\BROWSE packets. * * XXX - what other browser packets go out to that mailslot? */ static void dissect_mailslot_lanman(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { int offset = 0; guint8 cmd; proto_tree *tree = NULL; proto_item *item = NULL; guint32 periodicity; const guint8 *host_name; guint8 os_major_ver, os_minor_ver; const gchar *windows_version = NULL; guint namelen; col_set_str(pinfo->cinfo, COL_PROTOCOL, "BROWSER"); col_clear(pinfo->cinfo, COL_INFO); cmd = tvb_get_guint8(tvb, offset); /* Put in something, and replace it later */ col_add_str(pinfo->cinfo, COL_INFO, val_to_str(cmd, commands, "Unknown command:0x%02x")); if (parent_tree) { item = proto_tree_add_item(parent_tree, proto_smb_browse, tvb, offset, -1, ENC_NA); tree = proto_item_add_subtree(item, ett_browse); } /* command */ proto_tree_add_uint(tree, hf_command, tvb, offset, 1, cmd); offset += 1; switch (cmd) { case BROWSE_DOMAIN_ANNOUNCEMENT: case BROWSE_LOCAL_MASTER_ANNOUNCEMENT: case BROWSE_HOST_ANNOUNCE: /* update count */ proto_tree_add_item(tree, hf_update_count, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* server type flags */ offset = dissect_smb_server_type_flags( tvb, offset, pinfo, tree, NULL, TRUE); /* OS version string (See "OSVERSIONINFO Structure" on MSDN) */ os_major_ver = tvb_get_guint8(tvb, offset); os_minor_ver = tvb_get_guint8(tvb, offset+1); SET_WINDOWS_VERSION_STRING(os_major_ver, os_minor_ver, windows_version); if(windows_version) proto_tree_add_text(tree, tvb, offset, 2, "Windows version: %s", windows_version); /* OS major version */ proto_tree_add_item(tree, hf_os_major, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* OS minor version */ proto_tree_add_item(tree, hf_os_minor, tvb, offset, 1, ENC_LITTLE_ENDIAN); offset += 1; /* periodicity (in seconds; convert to milliseconds) */ periodicity = tvb_get_letohs(tvb, offset)*1000; proto_tree_add_uint_format(tree, hf_periodicity, tvb, offset, 2, periodicity, "Update Periodicity: %s", time_msecs_to_str(periodicity)); offset += 2; /* server name */ host_name = tvb_get_const_stringz(tvb, offset, &namelen); col_append_fstr(pinfo->cinfo, COL_INFO, " %s", host_name); proto_tree_add_item(tree, hf_server_name, tvb, offset, namelen, ENC_ASCII|ENC_NA); offset += namelen; /* master browser server name or server comment */ namelen = tvb_strsize(tvb, offset); proto_tree_add_item(tree, (cmd==BROWSE_DOMAIN_ANNOUNCEMENT)? hf_mb_server_name : hf_server_comment, tvb, offset, namelen, ENC_ASCII|ENC_NA); break; } }
/* Dissect OSC bundle */ static int dissect_osc_bundle(tvbuff_t *tvb, proto_item *ti, proto_tree *osc_tree, gint offset, gint len) { const gchar *str; proto_tree *bundle_tree = NULL; gint end = offset + len; guint32 sec; guint32 frac; nstime_t ns; /* check for valid #bundle */ str = tvb_get_const_stringz(tvb, offset, NULL); if(strncmp(str, bundle_str, 8)) /* no OSC bundle */ return -1; /* create bundle */ ti = proto_tree_add_item(osc_tree, hf_osc_bundle_type, tvb, offset, len, ENC_NA); bundle_tree = proto_item_add_subtree(ti, ett_osc_bundle); offset += 8; /* skip bundle_str */ /* read timetag */ sec = tvb_get_ntohl(tvb, offset); frac = tvb_get_ntohl(tvb, offset+4); if( (sec == 0UL) && (frac == 1UL) ) proto_tree_add_time_format_value(bundle_tree, hf_osc_bundle_timetag_type, tvb, offset, 8, &ns, immediate_fmt, immediate_str); else proto_tree_add_item(bundle_tree, hf_osc_bundle_timetag_type, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN); offset += 8; /* ::read size, read block:: */ while(offset < end) { /* peek bundle element size */ gint32 size = tvb_get_ntohl(tvb, offset); /* read bundle element size */ proto_tree_add_int_format_value(bundle_tree, hf_osc_bundle_element_size_type, tvb, offset, 4, size, "%i bytes", size); offset += 4; /* check for zero size bundle element */ if(size == 0) continue; /* peek first bundle element char */ switch(tvb_get_guint8(tvb, offset)) { case '#': /* this is a bundle */ if(dissect_osc_bundle(tvb, ti, bundle_tree, offset, size)) return -1; else break; case '/': /* this is a message */ if(dissect_osc_message(tvb, ti, bundle_tree, offset, size)) return -1; else break; default: return -1; /* neither message nor bundle */ } /* check for integer overflow */ if(size > G_MAXINT - offset) return -1; else offset += size; } if(offset != end) return -1; else return 0; }
/* Dissect OSC message */ static int dissect_osc_message(tvbuff_t *tvb, proto_item *ti, proto_tree *osc_tree, gint offset, gint len) { proto_tree *message_tree = NULL; proto_tree *header_tree = NULL; gint slen; gint rem; gint end = offset + len; const gchar *path = NULL; gint path_len; gint path_offset; const gchar *format = NULL; gint format_offset; gint format_len; const gchar *ptr = NULL; /* peek/read path */ path_offset = offset; path = tvb_get_const_stringz(tvb, path_offset, &path_len); if( (rem = path_len%4) ) path_len += 4-rem; if(!is_valid_path(path)) return -1; /* peek/read fmt */ format_offset = path_offset + path_len; format = tvb_get_const_stringz(tvb, format_offset, &format_len); if( (rem = format_len%4) ) format_len += 4-rem; if(!is_valid_format(format)) return -1; /* create message */ ti = proto_tree_add_none_format(osc_tree, hf_osc_message_type, tvb, offset, len, "Message: %s %s", path, format); message_tree = proto_item_add_subtree(ti, ett_osc_message); /* append header */ ti = proto_tree_add_item(message_tree, hf_osc_message_header_type, tvb, offset, path_len+format_len, ENC_NA); header_tree = proto_item_add_subtree(ti, ett_osc_message_header); /* append path */ proto_tree_add_item(header_tree, hf_osc_message_path_type, tvb, path_offset, path_len, ENC_ASCII | ENC_NA); /* append format */ proto_tree_add_item(header_tree, hf_osc_message_format_type, tvb, format_offset, format_len, ENC_ASCII | ENC_NA); offset += path_len + format_len; /* ::parse argument:: */ ptr = format + 1; /* skip ',' */ while( (*ptr != '\0') && (offset < end) ) { switch(*ptr) { case OSC_INT32: proto_tree_add_item(message_tree, hf_osc_message_int32_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case OSC_FLOAT: proto_tree_add_item(message_tree, hf_osc_message_float_type, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case OSC_STRING: slen = tvb_strsize(tvb, offset); if( (rem = slen%4) ) slen += 4-rem; proto_tree_add_item(message_tree, hf_osc_message_string_type, tvb, offset, slen, ENC_ASCII | ENC_NA); offset += slen; break; case OSC_BLOB: { proto_item *bi = NULL; proto_tree *blob_tree = NULL; gint32 blen = tvb_get_ntohl(tvb, offset); slen = blen; if( (rem = slen%4) ) slen += 4-rem; bi = proto_tree_add_none_format(message_tree, hf_osc_message_blob_type, tvb, offset, 4+slen, "Blob: %i bytes", blen); blob_tree = proto_item_add_subtree(bi, ett_osc_blob); proto_tree_add_int_format_value(blob_tree, hf_osc_message_blob_size_type, tvb, offset, 4, blen, "%i bytes", blen); offset += 4; /* check for zero length blob */ if(blen == 0) break; proto_tree_add_item(blob_tree, hf_osc_message_blob_data_type, tvb, offset, slen, ENC_NA); offset += slen; break; } case OSC_TRUE: proto_tree_add_item(message_tree, hf_osc_message_true_type, tvb, offset, 0, ENC_NA); break; case OSC_FALSE: proto_tree_add_item(message_tree, hf_osc_message_false_type, tvb, offset, 0, ENC_NA); break; case OSC_NIL: proto_tree_add_item(message_tree, hf_osc_message_nil_type, tvb, offset, 0, ENC_NA); break; case OSC_BANG: proto_tree_add_item(message_tree, hf_osc_message_bang_type, tvb, offset, 0, ENC_NA); break; case OSC_INT64: proto_tree_add_item(message_tree, hf_osc_message_int64_type, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; break; case OSC_DOUBLE: proto_tree_add_item(message_tree, hf_osc_message_double_type, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; break; case OSC_TIMETAG: { guint32 sec = tvb_get_ntohl(tvb, offset); guint32 frac = tvb_get_ntohl(tvb, offset+4); nstime_t ns; if( (sec == 0UL) && (frac == 1UL) ) proto_tree_add_time_format_value(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, &ns, immediate_fmt, immediate_str); else proto_tree_add_item(message_tree, hf_osc_message_timetag_type, tvb, offset, 8, ENC_TIME_NTP | ENC_BIG_ENDIAN); offset += 8; } break; case OSC_SYMBOL: slen = tvb_strsize(tvb, offset); if( (rem = slen%4) ) slen += 4-rem; proto_tree_add_item(message_tree, hf_osc_message_symbol_type, tvb, offset, slen, ENC_ASCII | ENC_NA); offset += slen; break; case OSC_CHAR: offset += 3; proto_tree_add_item(message_tree, hf_osc_message_char_type, tvb, offset, 1, ENC_ASCII | ENC_NA); offset += 1; break; case OSC_RGBA: { proto_item *ri = NULL; proto_tree *rgba_tree = NULL; ri = proto_tree_add_item(message_tree, hf_osc_message_rgba_type, tvb, offset, 4, ENC_BIG_ENDIAN); rgba_tree = proto_item_add_subtree(ri, ett_osc_rgba); proto_tree_add_item(rgba_tree, hf_osc_message_rgba_red_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_green_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_blue_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(rgba_tree, hf_osc_message_rgba_alpha_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; break; } case OSC_MIDI: { const gchar *status_str = NULL; const gchar *control_str = NULL; proto_item *mi = NULL; proto_tree *midi_tree = NULL; guint8 channel; guint8 status; guint8 data1; guint8 data2; channel = tvb_get_guint8(tvb, offset); status = tvb_get_guint8(tvb, offset+1); data1 = tvb_get_guint8(tvb, offset+2); data2 = tvb_get_guint8(tvb, offset+3); status_str = val_to_str_const(status, MIDI_status, "Unknown"); if(status == MIDI_STATUS_CONTROLLER) /* MIDI Controller */ { control_str = val_to_str_const(data1, MIDI_control, "Unknown"); mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Channel %2i, %s (0x%02x), %s (0x%02x), 0x%02x", channel, status_str, status, control_str, data1, data2); } else mi = proto_tree_add_none_format(message_tree, hf_osc_message_midi_type, tvb, offset, 4, "MIDI: Channel %2i, %s (0x%02x), 0x%02x, 0x%02x", channel, status_str, status, data1, data2); midi_tree = proto_item_add_subtree(mi, ett_osc_midi); proto_tree_add_item(midi_tree, hf_osc_message_midi_channel_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_status_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if(status == MIDI_STATUS_CONTROLLER) { proto_tree_add_item(midi_tree, hf_osc_message_midi_controller_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_value_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } else { proto_tree_add_item(midi_tree, hf_osc_message_midi_data1_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(midi_tree, hf_osc_message_midi_data2_type, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; } break; } default: /* if we get here, there must be a bug in the dissector */ DISSECTOR_ASSERT_NOT_REACHED(); break; } ptr++; } if(offset != end) return -1; else return 0; }
} } } /* OSC heuristics */ static gboolean dissect_osc_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { gint offset = 0; gint slen; gint rem; const gchar *str = NULL; conversation_t *conversation = NULL; /* peek first string */ str = tvb_get_const_stringz(tvb, offset, &slen); if(strncmp(str, bundle_str, 8) != 0) /* no OSC bundle */ { /* check for valid path */ if(!is_valid_path(str)) return FALSE; /* skip path */ if( (rem = slen%4) ) slen += 4-rem; offset += slen; /* peek next string */ str = tvb_get_const_stringz(tvb, offset, &slen); /* check for valid format */ if(!is_valid_format(str))