2 * Routines for SoulSeek Protocol dissection
3 * Copyright 2003, Christian Wagner <Christian.Wagner@stud.uni-karlsruhe.de>
4 * Institute of Telematics - University of Karlsruhe
5 * part of this work supported by
6 * Deutsche Forschungsgemeinschaft (DFG) Grant Number FU448/1
8 * SoulSeek Protocol dissector based on protocol descriptions from SoleSeek Project:
9 * http://cvs.sourceforge.net/viewcvs.py/soleseek/SoleSeek/doc/protocol.html?rev=HEAD
10 * Updated for SoulSeek client version 151
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * SPDX-License-Identifier: GPL-2.0-or-later
22 #include <epan/packet.h>
23 #include <epan/prefs.h>
24 #include <epan/strutil.h>
25 #include <epan/expert.h>
26 #include "packet-tcp.h"
28 void proto_register_slsk(void);
29 void proto_reg_handoff_slsk(void);
31 static dissector_handle_t slsk_handle
;
33 /* Initialize the protocol and registered fields */
34 static int proto_slsk
;
36 static int hf_slsk_integer
;
37 static int hf_slsk_string
;
38 static int hf_slsk_byte
;
39 static int hf_slsk_message_length
;
40 static int hf_slsk_message_code
;
41 static int hf_slsk_embedded_message_type
;
42 static int hf_slsk_client_ip
;
43 /* static int hf_slsk_server_ip; */
44 static int hf_slsk_directory_name
;
45 static int hf_slsk_username
;
46 static int hf_slsk_password
;
47 static int hf_slsk_version
;
48 static int hf_slsk_login_successful
;
49 static int hf_slsk_login_message
;
50 static int hf_slsk_port
;
51 static int hf_slsk_ip
;
52 static int hf_slsk_user_exists
;
53 static int hf_slsk_status_code
;
54 static int hf_slsk_room
;
55 static int hf_slsk_chat_message
;
56 static int hf_slsk_users_in_room
;
57 static int hf_slsk_token
;
58 static int hf_slsk_connection_type
;
59 static int hf_slsk_chat_message_id
;
60 static int hf_slsk_timestamp
;
61 static int hf_slsk_search_text
;
62 static int hf_slsk_folder_count
;
63 static int hf_slsk_file_count
;
64 static int hf_slsk_average_speed
;
65 static int hf_slsk_download_number
;
66 static int hf_slsk_files
;
67 static int hf_slsk_directories
;
68 static int hf_slsk_slotsfull
;
69 static int hf_slsk_place_in_queue
;
70 static int hf_slsk_number_of_rooms
;
71 static int hf_slsk_filename
;
72 static int hf_slsk_filename_ext
;
73 static int hf_slsk_directory
;
74 static int hf_slsk_size
;
75 /* static int hf_slsk_checksum; */
76 static int hf_slsk_code
;
77 static int hf_slsk_number_of_users
;
78 static int hf_slsk_number_of_days
;
79 static int hf_slsk_transfer_direction
;
80 static int hf_slsk_user_description
;
81 static int hf_slsk_picture_exists
;
82 static int hf_slsk_picture
;
83 /* static int hf_slsk_user_uploads; */
84 static int hf_slsk_total_uploads
;
85 static int hf_slsk_queued_uploads
;
86 static int hf_slsk_slots_available
;
87 static int hf_slsk_allowed
;
88 static int hf_slsk_compr_packet
;
89 static int hf_slsk_parent_min_speed
;
90 static int hf_slsk_parent_speed_connection_ratio
;
91 static int hf_slsk_seconds_parent_inactivity_before_disconnect
;
92 static int hf_slsk_seconds_server_inactivity_before_disconnect
;
93 static int hf_slsk_nodes_in_cache_before_disconnect
;
94 static int hf_slsk_seconds_before_ping_children
;
95 static int hf_slsk_recommendation
;
96 static int hf_slsk_user
;
97 static int hf_slsk_ranking
;
98 static int hf_slsk_compressed_packet_length
;
99 static int hf_slsk_uncompressed_packet_length
;
100 static int hf_slsk_num_directories
;
101 static int hf_slsk_upload_speed
;
102 static int hf_slsk_in_queue
;
103 static int hf_slsk_num_slotsfull_records
;
104 static int hf_slsk_num_recommendations
;
105 static int hf_slsk_num_files
;
106 static int hf_slsk_num_strings
;
107 static int hf_slsk_file_code
;
108 static int hf_slsk_file_size1
;
109 static int hf_slsk_file_size2
;
110 static int hf_slsk_file_num_attributes
;
111 static int hf_slsk_file_attribute_type
;
112 static int hf_slsk_file_attribute_value
;
113 static int hf_slsk_free_upload_slots
;
114 static int hf_slsk_bytes
;
115 static int hf_slsk_same_recommendation
;
116 static int hf_slsk_number_of_priv_users
;
117 static int hf_slsk_num_parent_address
;
119 /* Initialize the subtree pointers */
121 static int ett_slsk_compr_packet
;
122 static int ett_slsk_directory
;
123 static int ett_slsk_file
;
124 static int ett_slsk_file_attribute
;
125 static int ett_slsk_user
;
126 static int ett_slsk_recommendation
;
127 static int ett_slsk_room
;
128 static int ett_slsk_string
;
130 static expert_field ei_slsk_unknown_data
;
131 static expert_field ei_slsk_zlib_decompression_failed
;
132 static expert_field ei_slsk_decompression_failed
;
134 #define SLSK_TCP_PORT_RANGE "2234,2240,5534"
137 /* desegmentation of SoulSeek Message over TCP */
138 static bool slsk_desegment
= true;
139 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
140 static bool slsk_decompress
= true;
142 static bool slsk_decompress
;
145 static const value_string slsk_tcp_msgs
[] = {
147 { 2, "Set Wait Port"},
148 { 3, "Get Peer Address"},
149 { 4, "Get Shared File List"},
150 { 5, "User Exists / Shared File List"},
151 { 7, "Get User Status"},
152 { 9, "File Search Result"},
153 { 13, "Say ChatRoom"},
155 { 15, "Leave Room / User Info Request"},
156 { 16, "User Joined Room / User Info Reply"},
157 { 17, "User Left Room"},
158 { 18, "Connect To Peer"},
159 { 22, "Message User"},
160 { 23, "Message User Ack"},
161 { 26, "File Search"},
164 { 34, "Update Upload Speed"},
165 { 35, "Shared Files & Folders"},
166 { 36, "Get User Stats / Folder Contents Request"},
167 { 37, "Folder Contents Response"},
168 { 40, "Queued Downloads / Transfer Request"},
169 { 41, "Transfer Response"},
170 { 42, "Placehold Upload"},
171 { 43, "Queue Upload"},
172 { 44, "Place In Queue"},
173 { 46, "Upload Failed"},
174 { 50, "Queue Failed / Own Recommendation"},
175 { 51, "Add Things I like / Place In Queue Request"},
176 { 52, "Remove Things I like"},
177 { 54, "Get Recommendations"},
179 { 56, "Get Global Rankings"},
180 { 57, "Get User Recommendations"},
181 { 58, "Admin Command"},
182 { 60, "Place In Line Response"},
184 { 63, "Room Removed"},
186 { 65, "Exact File Search"},
187 { 66, "Admin Message"},
188 { 67, "Global User List"},
189 { 68, "Tunneled Message"},
190 { 69, "Privileged User List"},
191 { 71, "Get Parent List"},
193 { 83, "Parent Min Speed"},
194 { 84, "Parent Speed Connection Ratio"},
195 { 86, "Parent Inactivity Before Disconnect"},
196 { 87, "Server Inactivity Before Disconnect"},
197 { 88, "Nodes In Cache Before Disconnect"},
198 { 90, "Seconds Before Ping Children"},
199 { 91, "Add To Privileged"},
200 { 92, "Check Privileges"},
201 { 93, "Embedded Message"},
202 { 100, "Become Parent"},
203 { 102, "Random Parent Addresses"},
204 { 103, "Send Wishlist Entry"},
206 { 110, "Get Similar Users"},
207 { 111, "Get Recommendations for Item"},
208 { 112, "Get Similar Users for Item"},
209 { 1001, "Can't Connect To Peer"},
213 static const value_string slsk_status_codes
[] = {
221 static const value_string slsk_transfer_direction
[] = {
227 static const value_string slsk_yes_no
[] = {
233 static const value_string slsk_attr_type
[] = {
240 static const char* connection_type(char con_type
[]) {
241 if (strlen(con_type
) != 1) return "Unknown";
242 if (con_type
[0] == 'D') return "Distributed Search";
243 if (con_type
[0] == 'P') return "Peer Connection"; /* "File Search Result / User Info Request / Get Shared File List" */
244 if (con_type
[0] == 'F') return "File Transfer";
248 // NOLINTNEXTLINE(misc-no-recursion)
249 static bool check_slsk_format(tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, const char format
[]){
252 * Returns true if tvbuff beginning at offset matches a certain format
253 * The format is given by an array of characters standing for a special field type
254 * i - integer (4 bytes)
256 * s - string (string_length + 4 bytes)
258 * * - can be used at the end of a format to ignore any following bytes
261 switch ( format
[0] ) {
263 if (tvb_captured_length_remaining(tvb
, offset
) < 4) return false;
267 if (tvb_captured_length_remaining(tvb
, offset
) < 1) return false;
271 if (tvb_captured_length_remaining(tvb
, offset
) < 4) return false;
272 if (tvb_captured_length_remaining(tvb
, offset
) < (int)tvb_get_letohl(tvb
, offset
)+4) return false;
273 offset
+= tvb_get_letohl(tvb
, offset
)+4;
281 if (format
[1] == '\0' ) {
282 if (tvb_captured_length_remaining(tvb
, offset
) > 0) /* Checks for additional bytes at the end */
286 increment_dissection_depth(pinfo
);
287 bool valid
= check_slsk_format(tvb
, pinfo
, offset
, &format
[1]);
288 decrement_dissection_depth(pinfo
);
293 static const char* get_message_type(tvbuff_t
*tvb
, packet_info
*pinfo
) {
295 * Checks if the Message Code is known.
296 * If unknown checks if the Message Code is stored in a byte.
297 * Returns the Message Type.
299 int msg_code
= tvb_get_letohl(tvb
, 4);
300 const char *message_type
= try_val_to_str(msg_code
, slsk_tcp_msgs
);
301 if (message_type
== NULL
) {
302 if (check_slsk_format(tvb
, pinfo
, 4, "bisis"))
303 message_type
= "Distributed Search";
304 else if (check_slsk_format(tvb
, pinfo
, 4, "bssi"))
305 message_type
= "Peer Init";
306 else if (check_slsk_format(tvb
, pinfo
, 4, "bi"))
307 message_type
= "Pierce Fw";
309 message_type
= "Unknown";
314 static unsigned get_slsk_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
,
315 int offset
, void *data _U_
)
318 msg_len
= tvb_get_letohl(tvb
, offset
);
319 /* That length doesn't include the length field itself; add that in. */
324 /* Code to actually dissect the packets */
326 static int dissect_slsk_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
329 /* Set up structures needed to add the protocol subtree and manage it */
330 proto_item
*ti
, *ti_len
, *ti_subtree
, *ti_subtree2
;
331 proto_tree
*slsk_tree
, *subtree
, *subtree2
, *subtree3
;
333 int offset
= 0, i
, j
;
334 uint32_t msg_len
, msg_code
;
336 int str_len
, start_offset
, start_offset2
;
338 int comprlen
= 0, uncomprlen
= 0, uncompr_tvb_offset
= 0;
342 /* Make entries in Protocol column and Info column on summary display */
343 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "slsk");
345 /* This field shows up as the "Info" column in the display */
347 col_set_str(pinfo
->cinfo
, COL_INFO
, "SoulSeek Message");
349 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": %s", get_message_type(tvb
, pinfo
));
351 /* create display subtree for the protocol */
352 ti
= proto_tree_add_item(tree
, proto_slsk
, tvb
, 0, -1, ENC_NA
);
353 slsk_tree
= proto_item_add_subtree(ti
, ett_slsk
);
355 /* Continue adding tree items to process the packet here */
357 ti_len
= proto_tree_add_item_ret_uint(slsk_tree
, hf_slsk_message_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &msg_len
);
359 msg_code
= tvb_get_letohl(tvb
, offset
);
364 if (check_slsk_format(tvb
, pinfo
, offset
, "issi")) {
365 /* Client-to-Server */
366 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
367 "Login (Code: %02d)", msg_code
);
369 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
371 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_password
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
373 proto_tree_add_item(slsk_tree
, hf_slsk_version
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
376 else if (check_slsk_format(tvb
, pinfo
, offset
, "ibs") || check_slsk_format(tvb
, pinfo
, offset
, "ibsi")) {
377 /* Server-to-Client */
378 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
379 "Login Reply (Code: %02d)", msg_code
);
381 i
=tvb_get_uint8(tvb
, offset
);
382 proto_tree_add_item(slsk_tree
, hf_slsk_login_successful
, tvb
, offset
, 1, ENC_NA
);
384 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_login_message
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
387 proto_tree_add_item(slsk_tree
, hf_slsk_client_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
394 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
395 /* Client-to-Server */
396 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
397 "Set Wait Port (Code: %02d)", msg_code
);
399 proto_tree_add_item(slsk_tree
, hf_slsk_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
405 if (check_slsk_format(tvb
, pinfo
, offset
, "isii")) {
406 /* Server-to-Client */
407 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
408 "Get Peer Address Reply (Code: %02d)", msg_code
);
410 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
412 proto_tree_add_item(slsk_tree
, hf_slsk_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
414 proto_tree_add_item(slsk_tree
, hf_slsk_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
417 else if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
418 /* Client-to-Server */
419 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
420 "Get Peer Address (Code: %02d)", msg_code
);
422 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
428 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
429 /* Client-to-Client */
430 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
431 "Get Shared File List (Code: %02d)", msg_code
);
437 if (check_slsk_format(tvb
, pinfo
, offset
, "isb")) {
438 /* Server-to-Client */
439 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
440 "User Exists Reply (Code: %02d)", msg_code
);
442 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
444 proto_tree_add_item(slsk_tree
, hf_slsk_user_exists
, tvb
, offset
, 1, ENC_NA
);
447 else if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
448 /* Client-to-Server */
449 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
450 "User Exists Request (Code: %02d)", msg_code
);
452 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
455 else if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
456 /* Client-to-Client */
457 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
458 "Shared File List (Code: %02d)", msg_code
);
461 /* [zlib compressed] */
462 comprlen
= tvb_captured_length_remaining(tvb
, offset
);
464 if (slsk_decompress
== true){
466 tvbuff_t
*uncompr_tvb
= tvb_child_uncompress_zlib(tvb
, tvb
, offset
, comprlen
);
468 if (uncompr_tvb
== NULL
) {
469 proto_tree_add_expert(slsk_tree
, pinfo
, &ei_slsk_zlib_decompression_failed
, tvb
, offset
, -1);
470 offset
+= tvb_captured_length_remaining(tvb
, offset
);
473 proto_item
*ti2
= proto_tree_add_item(slsk_tree
, hf_slsk_compr_packet
, tvb
, offset
, -1, ENC_NA
);
474 proto_tree
*slsk_compr_packet_tree
= proto_item_add_subtree(ti2
, ett_slsk_compr_packet
);
475 proto_item_set_generated(ti2
);
477 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_compressed_packet_length
, tvb
, offset
, 0, comprlen
);
478 proto_item_set_generated(ti
);
479 uncomprlen
= tvb_reported_length_remaining(uncompr_tvb
, 0);
480 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_uncompressed_packet_length
, tvb
, offset
, 0, uncomprlen
);
481 proto_item_set_generated(ti
);
483 add_new_data_source(pinfo
, uncompr_tvb
, "Uncompressed SoulSeek data");
484 uncompr_tvb_offset
= 0;
485 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "i*")) {
486 proto_tree_add_item_ret_int(slsk_compr_packet_tree
, hf_slsk_num_directories
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
487 uncompr_tvb_offset
+= 4;
488 for (i
= 0; i
< j
; i
++) {
489 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "si*")) {
490 start_offset
= uncompr_tvb_offset
;
491 subtree
= proto_tree_add_subtree_format(slsk_compr_packet_tree
, uncompr_tvb
, uncompr_tvb_offset
, 1, ett_slsk_directory
, &ti_subtree
, "Directory #%d", i
+1);
492 proto_tree_add_item_ret_length(subtree
, hf_slsk_directory_name
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
493 uncompr_tvb_offset
+= str_len
;
494 proto_tree_add_item_ret_int(subtree
, hf_slsk_num_files
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
, &j2
);
495 uncompr_tvb_offset
+= 4;
496 for (i2
= 0; i2
< j2
; i2
++) {
497 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "bsiisi*")) {
498 start_offset2
= uncompr_tvb_offset
;
499 subtree2
= proto_tree_add_subtree_format(subtree
, uncompr_tvb
, uncompr_tvb_offset
, 1, ett_slsk_file
, &ti_subtree2
, "File #%d", i2
+1);
500 proto_tree_add_item(subtree2
, hf_slsk_file_code
, uncompr_tvb
, uncompr_tvb_offset
, 1, ENC_NA
);
501 uncompr_tvb_offset
+= 1;
502 proto_tree_add_item_ret_length(subtree2
, hf_slsk_filename
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
503 uncompr_tvb_offset
+= str_len
;
504 proto_tree_add_item(subtree2
, hf_slsk_file_size1
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
505 uncompr_tvb_offset
+= 4;
506 proto_tree_add_item(subtree2
, hf_slsk_file_size2
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
507 uncompr_tvb_offset
+= 4;
508 proto_tree_add_item_ret_length(subtree2
, hf_slsk_filename_ext
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
509 uncompr_tvb_offset
+= str_len
;
510 proto_tree_add_item_ret_int(subtree2
, hf_slsk_file_num_attributes
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
, &j3
);
511 uncompr_tvb_offset
+= 4;
512 for (i3
= 0; i3
< j3
; i3
++) {
513 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "ii*")) {
514 subtree3
= proto_tree_add_subtree_format(subtree2
, uncompr_tvb
, uncompr_tvb_offset
, 8, ett_slsk_file_attribute
, NULL
, "Attribute #%d", i3
+1);
515 proto_tree_add_item(subtree3
, hf_slsk_file_attribute_type
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
516 uncompr_tvb_offset
+= 4;
517 proto_tree_add_item(subtree3
, hf_slsk_file_attribute_value
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
518 uncompr_tvb_offset
+= 4;
520 break; /* invalid format */
523 proto_item_set_len(ti_subtree2
, uncompr_tvb_offset
-start_offset2
);
525 break; /* invalid format */
528 proto_item_set_len(ti_subtree
, uncompr_tvb_offset
-start_offset
);
530 break; /* invalid format */
536 ti
= proto_tree_add_item(slsk_tree
, hf_slsk_compr_packet
, tvb
, offset
, -1, ENC_NA
);
537 proto_item_set_generated(ti
);
538 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_compressed_packet_length
, tvb
, offset
, 0, comprlen
);
539 proto_item_set_generated(ti
);
540 offset
+= tvb_captured_length_remaining(tvb
, offset
);
546 if (check_slsk_format(tvb
, pinfo
, offset
, "isi")) {
547 /* Server-to-Client */
548 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
549 "Get User Status Reply (Code: %02d)", msg_code
);
551 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
553 proto_tree_add_item(slsk_tree
, hf_slsk_status_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
556 else if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
557 /* Client-to-Server */
558 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
559 "Get User Status (Code: %02d)", msg_code
);
561 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
567 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
568 /* Client-to-Client */
569 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
570 "File Search Result (Code: %02d)", msg_code
);
573 /* [zlib compressed] */
574 comprlen
= tvb_captured_length_remaining(tvb
, offset
);
576 if (slsk_decompress
== true){
578 tvbuff_t
*uncompr_tvb
= tvb_child_uncompress_zlib(tvb
, tvb
, offset
, comprlen
);
580 if (uncompr_tvb
== NULL
) {
581 ti
= proto_tree_add_item(slsk_tree
, hf_slsk_compr_packet
, tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
), ENC_NA
);
582 proto_item_set_generated(ti
);
583 offset
+= tvb_captured_length_remaining(tvb
, offset
);
584 expert_add_info(pinfo
, ti
, &ei_slsk_decompression_failed
);
587 proto_item
*ti2
= proto_tree_add_item(slsk_tree
, hf_slsk_compr_packet
, tvb
, offset
, -1, ENC_NA
);
588 proto_tree
*slsk_compr_packet_tree
= proto_item_add_subtree(ti2
, ett_slsk_compr_packet
);
589 proto_item_set_generated(ti2
);
591 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_compressed_packet_length
, tvb
, offset
, 0, comprlen
);
592 proto_item_set_generated(ti
);
593 uncomprlen
= tvb_captured_length_remaining(uncompr_tvb
, 0);
594 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_uncompressed_packet_length
, tvb
, offset
, 0, uncomprlen
);
595 proto_item_set_generated(ti
);
597 add_new_data_source(pinfo
, uncompr_tvb
, "Uncompressed SoulSeek data");
598 uncompr_tvb_offset
= 0;
599 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "sii*")) {
600 proto_tree_add_item_ret_length(slsk_compr_packet_tree
, hf_slsk_username
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_NA
, &str_len
);
601 uncompr_tvb_offset
+= str_len
;
602 proto_tree_add_item(slsk_compr_packet_tree
, hf_slsk_token
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
603 uncompr_tvb_offset
+= 4;
604 proto_tree_add_item_ret_int(slsk_compr_packet_tree
, hf_slsk_num_files
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
605 uncompr_tvb_offset
+= 4;
606 for (i
= 0; i
< j
; i
++) {
607 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "bsiisi*")) {
608 start_offset2
= uncompr_tvb_offset
;
609 subtree2
= proto_tree_add_subtree_format(slsk_compr_packet_tree
, uncompr_tvb
, uncompr_tvb_offset
, 1, ett_slsk_file
, &ti_subtree2
, "File #%d", i
+1);
610 proto_tree_add_item(subtree2
, hf_slsk_file_code
, uncompr_tvb
, uncompr_tvb_offset
, 1, ENC_NA
);
611 uncompr_tvb_offset
+= 1;
612 proto_tree_add_item_ret_length(subtree2
, hf_slsk_filename
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
613 uncompr_tvb_offset
+= str_len
;
614 proto_tree_add_item(subtree2
, hf_slsk_file_size1
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
615 uncompr_tvb_offset
+= 4;
616 proto_tree_add_item(subtree2
, hf_slsk_file_size2
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
617 uncompr_tvb_offset
+= 4;
618 proto_tree_add_item_ret_length(subtree2
, hf_slsk_filename_ext
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
619 uncompr_tvb_offset
+= str_len
;
620 proto_tree_add_item_ret_int(subtree2
, hf_slsk_file_num_attributes
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
, &j2
);
621 uncompr_tvb_offset
+= 4;
622 for (i2
= 0; i2
< j2
; i2
++) {
623 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "ii*")) {
624 subtree3
= proto_tree_add_subtree_format(subtree2
, uncompr_tvb
, uncompr_tvb_offset
, 8, ett_slsk_file_attribute
, NULL
, "Attribute #%d", i2
+1);
625 proto_tree_add_item(subtree3
, hf_slsk_file_attribute_type
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
626 uncompr_tvb_offset
+= 4;
627 proto_tree_add_item(subtree3
, hf_slsk_file_attribute_value
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
628 uncompr_tvb_offset
+= 4;
630 break; /* invalid format */
633 proto_item_set_len(ti_subtree2
, uncompr_tvb_offset
-start_offset2
);
635 break; /* invalid format */
639 proto_tree_add_item(slsk_compr_packet_tree
, hf_slsk_free_upload_slots
, uncompr_tvb
, uncompr_tvb_offset
, 1, ENC_LITTLE_ENDIAN
);
640 uncompr_tvb_offset
+= 1;
641 proto_tree_add_item(slsk_compr_packet_tree
, hf_slsk_upload_speed
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
642 uncompr_tvb_offset
+= 4;
643 proto_tree_add_item(slsk_compr_packet_tree
, hf_slsk_in_queue
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
647 ti
= proto_tree_add_item(slsk_tree
, hf_slsk_compr_packet
, tvb
, offset
, -1, ENC_NA
);
648 proto_item_set_generated(ti
);
649 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_compressed_packet_length
, tvb
, offset
, 0, comprlen
);
650 proto_item_set_generated(ti
);
651 offset
+= tvb_captured_length_remaining(tvb
, offset
);
657 if (check_slsk_format(tvb
, pinfo
, offset
, "isss")) {
658 /* Server-to-Client */
659 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
660 "Say ChatRoom (Code: %02d)", msg_code
);
662 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
664 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
666 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_chat_message
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
669 else if (check_slsk_format(tvb
, pinfo
, offset
, "iss")) {
670 /* Client-to-Server */
671 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
672 "Say ChatRoom (Code: %02d)", msg_code
);
674 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
676 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_chat_message
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
682 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
683 /* Client-to-Server */
684 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
685 "Join/Add Room (Code: %02d)", msg_code
);
687 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
690 else if (check_slsk_format(tvb
, pinfo
, offset
, "isi*")) {
691 /* Server-to-Client */
692 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
693 "Join Room User List (Code: %02d)", msg_code
);
695 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
697 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_users_in_room
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
699 if (j
> tvb_reported_length_remaining(tvb
, offset
))
701 for (i
= 0; i
< j
; i
++) {
702 if (check_slsk_format(tvb
, pinfo
, offset
, "s*")) {
703 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_user
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
706 break; /* invalid format */
709 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
710 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_users_in_room
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
712 if (j
> tvb_reported_length_remaining(tvb
, offset
))
714 for (i
= 0; i
< j
; i
++) {
715 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
716 proto_tree_add_item(slsk_tree
, hf_slsk_status_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
719 break; /* invalid format */
723 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
724 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_users_in_room
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
726 if (j
> tvb_reported_length_remaining(tvb
, offset
))
728 for (i
= 0; i
< j
; i
++) {
729 if (check_slsk_format(tvb
, pinfo
, offset
, "iiiii*")) {
730 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 20, ett_slsk_user
, NULL
, "User #%d", i
+1);
731 proto_tree_add_item(subtree
, hf_slsk_average_speed
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
733 proto_tree_add_item(subtree
, hf_slsk_download_number
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
735 proto_tree_add_item(subtree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
737 proto_tree_add_item(subtree
, hf_slsk_files
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
739 proto_tree_add_item(subtree
, hf_slsk_directories
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
742 break; /* invalid format */
746 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
747 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_slotsfull_records
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
749 if (j
> tvb_reported_length_remaining(tvb
, offset
))
751 for (i
= 0; i
< j
; i
++) {
752 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
753 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 4, ett_slsk_user
, NULL
, "User #%d", i
+1);
754 proto_tree_add_item(subtree
, hf_slsk_slotsfull
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
757 break; /* invalid format */
765 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
766 /* Client-to-Server & Server-to-Client */
767 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
768 "Leave Room (Code: %02d)", msg_code
);
770 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
773 else if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
774 /* Client-to-Client */
775 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
776 "User Info Request (Code: %02d)", msg_code
);
782 if (check_slsk_format(tvb
, pinfo
, offset
, "issiiiiiii")) {
783 /* Server-to-Client */
784 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
785 "User Joined Room (Code: %02d)", msg_code
);
787 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
789 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
791 proto_tree_add_item(slsk_tree
, hf_slsk_total_uploads
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
793 proto_tree_add_item(slsk_tree
, hf_slsk_average_speed
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
795 proto_tree_add_item(slsk_tree
, hf_slsk_download_number
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
797 proto_tree_add_item(slsk_tree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
799 proto_tree_add_item(slsk_tree
, hf_slsk_files
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
801 proto_tree_add_item(slsk_tree
, hf_slsk_directories
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
803 proto_tree_add_item(slsk_tree
, hf_slsk_slotsfull
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
806 else if (check_slsk_format(tvb
, pinfo
, offset
, "isbiib") || check_slsk_format(tvb
, pinfo
, offset
, "isbsiib")) {
807 /* Client-to-Client */
808 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
809 "User Info Reply (Code: %02d)", msg_code
);
811 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_user_description
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
813 proto_tree_add_item(slsk_tree
, hf_slsk_picture_exists
, tvb
, offset
, 1, ENC_NA
);
815 if ( tvb_get_uint8(tvb
, offset
-1 ) == 1 ) {
816 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_picture
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
819 proto_tree_add_item(slsk_tree
, hf_slsk_total_uploads
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
821 proto_tree_add_item(slsk_tree
, hf_slsk_queued_uploads
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
823 proto_tree_add_item(slsk_tree
, hf_slsk_slots_available
, tvb
, offset
, 1, ENC_NA
);
829 if (check_slsk_format(tvb
, pinfo
, offset
, "iss")) {
830 /* Server-to-Client */
831 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
832 "User Left Room (Code: %02d)", msg_code
);
834 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
836 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
842 if (check_slsk_format(tvb
, pinfo
, offset
, "iiss")) {
843 /* Client-to-Server */
846 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
847 "Connect To Peer (Code: %02d)", msg_code
);
849 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
851 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
853 len
= tvb_get_letohl(tvb
, offset
);
854 str
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+4, len
, ENC_ASCII
);
855 proto_tree_add_string_format_value(slsk_tree
, hf_slsk_connection_type
, tvb
, offset
, 4+len
, str
,
856 "%s (Char: %s)", connection_type(str
),
857 format_text(pinfo
->pool
, str
, len
));
860 else if (check_slsk_format(tvb
, pinfo
, offset
, "issiii")) {
861 /* Server-to-Client */
864 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
865 "Connect To Peer (Code: %02d)", msg_code
);
867 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
869 len
= tvb_get_letohl(tvb
, offset
);
870 str
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+4, len
, ENC_ASCII
);
871 proto_tree_add_string_format_value(slsk_tree
, hf_slsk_connection_type
, tvb
, offset
, 4+len
, str
,
872 "%s (Char: %s)", connection_type(str
),
873 format_text(pinfo
->pool
, str
, len
));
875 proto_tree_add_item(slsk_tree
, hf_slsk_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
877 proto_tree_add_item(slsk_tree
, hf_slsk_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
879 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
885 if (check_slsk_format(tvb
, pinfo
, offset
, "iss")) {
886 /* Client-to-Server */
887 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
888 "Message User Send (Code: %02d)", msg_code
);
890 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
892 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_chat_message
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
895 else if (check_slsk_format(tvb
, pinfo
, offset
, "iiiss")) {
896 /* Server-to-Client */
897 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
898 "Message User Receive (Code: %02d)", msg_code
);
900 proto_tree_add_item(slsk_tree
, hf_slsk_chat_message_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
902 proto_tree_add_item(slsk_tree
, hf_slsk_timestamp
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
904 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
906 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_chat_message
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
912 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
913 /* Client-to-Server */
914 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
915 "Message User Receive Ack (Code: %02d)", msg_code
);
917 proto_tree_add_item(slsk_tree
, hf_slsk_chat_message_id
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
923 if (check_slsk_format(tvb
, pinfo
, offset
, "iis")) {
924 /* Client-to-Server */
925 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
926 "File Search (Code: %02d)", msg_code
);
928 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
930 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_search_text
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
936 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
937 /* Client-to-Server */
938 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
939 "Set Status (Code: %02d)", msg_code
);
941 proto_tree_add_item(slsk_tree
, hf_slsk_status_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
947 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
948 /* Client-to-Server */
949 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
950 "Ping (Code: %02d)", msg_code
);
956 if (check_slsk_format(tvb
, pinfo
, offset
, "isi")) {
957 /* Client-to-Server */
958 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
959 "Update Upload Speed (Code: %02d)", msg_code
);
961 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
963 proto_tree_add_item(slsk_tree
, hf_slsk_average_speed
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
969 if (check_slsk_format(tvb
, pinfo
, offset
, "iii")) {
970 /* Client-to-Server */
971 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
972 "Shared Files & Folders (Code: %02d)", msg_code
);
974 proto_tree_add_item(slsk_tree
, hf_slsk_folder_count
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
976 proto_tree_add_item(slsk_tree
, hf_slsk_file_count
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
982 if (check_slsk_format(tvb
, pinfo
, offset
, "isiiiii")) {
983 /* Server-to-Client */
984 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
985 "Get User Stats Reply (Code: %02d)", msg_code
);
987 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
989 proto_tree_add_item(slsk_tree
, hf_slsk_average_speed
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
991 proto_tree_add_item(slsk_tree
, hf_slsk_download_number
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
993 proto_tree_add_item(slsk_tree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
995 proto_tree_add_item(slsk_tree
, hf_slsk_files
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
997 proto_tree_add_item(slsk_tree
, hf_slsk_directories
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1000 else if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1001 /* Client-to-Client */
1002 /* Client-to-Server: send after login successful */
1003 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1004 "Get User Stats (Code: %02d)", msg_code
);
1006 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1009 else if (check_slsk_format(tvb
, pinfo
, offset
, "iis")) {
1010 /* Client-to-Client */
1011 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1012 "Folder Contents Request (Code: %02d)", msg_code
);
1014 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1016 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_directory
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1022 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
1023 /* Client-to-Client */
1024 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1025 "Folder Contents Response (Code: %02d)", msg_code
);
1028 /* [zlib compressed] */
1029 comprlen
= tvb_captured_length_remaining(tvb
, offset
);
1031 if (slsk_decompress
== true){
1033 tvbuff_t
*uncompr_tvb
= tvb_child_uncompress_zlib(tvb
, tvb
, offset
, comprlen
);
1035 if (uncompr_tvb
== NULL
) {
1036 proto_tree_add_expert(slsk_tree
, pinfo
, &ei_slsk_zlib_decompression_failed
, tvb
, offset
, -1);
1037 offset
+= tvb_captured_length_remaining(tvb
, offset
);
1040 proto_item
*ti2
= proto_tree_add_item(slsk_tree
, hf_slsk_compr_packet
, tvb
, offset
, -1, ENC_NA
);
1041 proto_tree
*slsk_compr_packet_tree
= proto_item_add_subtree(ti2
, ett_slsk_compr_packet
);
1042 proto_item_set_generated(ti2
);
1044 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_compressed_packet_length
, tvb
, offset
, 0, comprlen
);
1045 proto_item_set_generated(ti
);
1046 uncomprlen
= tvb_captured_length_remaining(uncompr_tvb
, 0);
1047 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_uncompressed_packet_length
, tvb
, offset
, 0, uncomprlen
);
1048 proto_item_set_generated(ti
);
1049 add_new_data_source(pinfo
, uncompr_tvb
, "Uncompressed SoulSeek data");
1051 uncompr_tvb_offset
= 0;
1052 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "isi*")) {
1055 proto_tree_add_item(slsk_compr_packet_tree
, hf_slsk_token
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
1056 uncompr_tvb_offset
+= 4;
1057 proto_tree_add_item_ret_length(slsk_compr_packet_tree
, hf_slsk_directory_name
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &len
);
1058 uncompr_tvb_offset
+= len
;
1060 proto_tree_add_item_ret_int(slsk_compr_packet_tree
, hf_slsk_num_directories
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1061 uncompr_tvb_offset
+= 4;
1062 for (i
= 0; i
< j
; i
++) {
1063 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "si*")) {
1064 start_offset
= uncompr_tvb_offset
;
1065 subtree
= proto_tree_add_subtree_format(slsk_compr_packet_tree
, uncompr_tvb
, uncompr_tvb_offset
, 1, ett_slsk_directory
, &ti_subtree
, "Directory #%d", i
+1);
1066 proto_tree_add_item_ret_length(subtree
, hf_slsk_directory_name
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1067 uncompr_tvb_offset
+= str_len
;
1068 proto_tree_add_item_ret_int(subtree
, hf_slsk_num_files
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
, &j2
);
1069 uncompr_tvb_offset
+= 4;
1070 for (i2
= 0; i2
< j2
; i2
++) {
1071 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "bsiisi*")) {
1072 start_offset2
= uncompr_tvb_offset
;
1073 subtree2
= proto_tree_add_subtree_format(subtree
, uncompr_tvb
, uncompr_tvb_offset
, 1, ett_slsk_file
, &ti_subtree2
, "File #%d", i2
+1);
1074 proto_tree_add_item(subtree2
, hf_slsk_file_code
, uncompr_tvb
, uncompr_tvb_offset
, 1, ENC_NA
);
1075 uncompr_tvb_offset
+= 1;
1076 proto_tree_add_item_ret_length(subtree2
, hf_slsk_filename
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1077 uncompr_tvb_offset
+= str_len
;
1078 proto_tree_add_item(subtree2
, hf_slsk_file_size1
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
1079 uncompr_tvb_offset
+= 4;
1080 proto_tree_add_item(subtree2
, hf_slsk_file_size2
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
1081 uncompr_tvb_offset
+= 4;
1082 proto_tree_add_item_ret_length(subtree2
, hf_slsk_filename_ext
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1083 uncompr_tvb_offset
+= str_len
;
1084 proto_tree_add_item_ret_int(subtree2
, hf_slsk_file_num_attributes
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
, &j3
);
1085 uncompr_tvb_offset
+= 4;
1086 for (i3
= 0; i3
< j3
; i3
++) {
1087 if (check_slsk_format(uncompr_tvb
, pinfo
, uncompr_tvb_offset
, "ii*")) {
1088 subtree3
= proto_tree_add_subtree_format(subtree2
, uncompr_tvb
, uncompr_tvb_offset
, 8, ett_slsk_file_attribute
, NULL
, "Attribute #%d", i3
+1);
1089 proto_tree_add_item(subtree3
, hf_slsk_file_attribute_type
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
1090 uncompr_tvb_offset
+= 4;
1091 proto_tree_add_item(subtree3
, hf_slsk_file_attribute_value
, uncompr_tvb
, uncompr_tvb_offset
, 4, ENC_LITTLE_ENDIAN
);
1092 uncompr_tvb_offset
+= 4;
1094 break; /* invalid format */
1097 proto_item_set_len(ti_subtree2
, uncompr_tvb_offset
-start_offset2
);
1099 break; /* invalid format */
1102 proto_item_set_len(ti_subtree
, uncompr_tvb_offset
-start_offset
);
1104 break; /* invalid format */
1110 ti
= proto_tree_add_item(slsk_tree
, hf_slsk_compr_packet
, tvb
, offset
, -1, ENC_NA
);
1111 proto_item_set_generated(ti
);
1112 ti
= proto_tree_add_uint(slsk_tree
, hf_slsk_compressed_packet_length
, tvb
, offset
, 0, comprlen
);
1113 proto_item_set_generated(ti
);
1114 offset
+= tvb_captured_length_remaining(tvb
, offset
);
1120 if (check_slsk_format(tvb
, pinfo
, offset
, "isi")) {
1121 /* Server-to-Client */
1122 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1123 "Queued Downloads (Code: %02d)", msg_code
);
1125 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1127 proto_tree_add_item(slsk_tree
, hf_slsk_slotsfull
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1130 else if (check_slsk_format(tvb
, pinfo
, offset
, "iiis") || check_slsk_format(tvb
, pinfo
, offset
, "iiisii")) {
1131 /* Client-to-Client */
1132 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1133 "Transfer Request (Code: %02d)", msg_code
);
1135 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_transfer_direction
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &i
);
1137 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1139 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1142 proto_tree_add_item(slsk_tree
, hf_slsk_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1144 proto_tree_add_item(slsk_tree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1152 if (check_slsk_format(tvb
, pinfo
, offset
, "iibs") || check_slsk_format(tvb
, pinfo
, offset
, "iibii") || check_slsk_format(tvb
, pinfo
, offset
, "iib")) {
1153 /* Client-to-Client */
1154 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1155 "Transfer Response (Code: %02d)", msg_code
);
1157 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1159 i
= tvb_get_uint8(tvb
, offset
);
1160 proto_tree_add_item(slsk_tree
, hf_slsk_allowed
, tvb
, offset
, 1, ENC_NA
);
1163 if ( tvb_reported_length_remaining(tvb
, offset
) == 8 ) {
1164 proto_tree_add_item(slsk_tree
, hf_slsk_size
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1166 proto_tree_add_item(slsk_tree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1170 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_string
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1177 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1178 /* Client-to-Client */
1179 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1180 "Placehold Upload (Code: %02d)", msg_code
);
1182 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1188 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1189 /* Client-to-Client */
1190 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1191 "Queue Upload (Code: %02d)", msg_code
);
1193 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1199 if (check_slsk_format(tvb
, pinfo
, offset
, "isi")) {
1200 /* Client-to-Client */
1201 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1202 "Place In Queue (Code: %02d)", msg_code
);
1204 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1206 proto_tree_add_item(slsk_tree
, hf_slsk_place_in_queue
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1212 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1213 /* Client-to-Client */
1214 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1215 "Upload Failed (Code: %02d)", msg_code
);
1217 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1223 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1224 /* Client-to-Server */
1225 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1226 "Make Own Recommendation (Code: %02d)", msg_code
);
1228 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1231 else if (check_slsk_format(tvb
, pinfo
, offset
, "isi")) {
1232 /* Client-to-Server */
1233 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1234 "Remove Own Recommendation (Code: %02d)", msg_code
);
1236 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1238 proto_tree_add_item(slsk_tree
, hf_slsk_ranking
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1241 else if (check_slsk_format(tvb
, pinfo
, offset
, "iss")) {
1242 /* Client-to-Client */
1243 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1244 "Queue Failed (Code: %02d)", msg_code
);
1246 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1248 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_string
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1254 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1255 /* Client-to-Server: "Add Things I like" */
1256 /* Client-to-Client: "Place In Queue Request" */
1257 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1258 "Add Things I like / Place In Queue Request (Code: %02d)", msg_code
);
1260 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1266 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1267 /* Client-to-Server */
1268 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1269 "Remove Things I like (Code: %02d)", msg_code
);
1271 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1277 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
1278 /* Client-to-Server */
1279 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1280 "Get Recommendations (Code: %02d)", msg_code
);
1283 else if (check_slsk_format(tvb
, pinfo
, offset
, "ii*")) {
1284 /* Server-to-Client */
1285 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1286 "Get Recommendations Reply (Code: %02d)", msg_code
);
1288 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_recommendations
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1290 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1292 for (i
= 0; i
< j
; i
++) {
1293 if (check_slsk_format(tvb
, pinfo
, offset
, "si*")) {
1294 start_offset
= offset
;
1295 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 1, ett_slsk_recommendation
, &ti_subtree
, "Recommendation #%d", i
+1);
1296 proto_tree_add_item_ret_length(subtree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1298 proto_tree_add_item(subtree
, hf_slsk_ranking
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1300 proto_item_set_len(ti_subtree
, offset
-start_offset
);
1302 break; /* invalid format */
1309 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
1310 /* Client-to-Server */
1311 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1312 "Type 55 (Code: %02d)", msg_code
);
1318 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
1319 /* Client-to-Server */
1320 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1321 "Get Global Rankings (Code: %02d)", msg_code
);
1324 else if (check_slsk_format(tvb
, pinfo
, offset
, "ii*")) {
1325 /* Server-to-Client */
1326 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1327 "Get Global Rankings Reply (Code: %02d)", msg_code
);
1329 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_recommendations
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1331 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1333 for (i
= 0; i
< j
; i
++) {
1334 if (check_slsk_format(tvb
, pinfo
, offset
, "si*")) {
1335 start_offset
= offset
;
1336 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 1, ett_slsk_recommendation
, &ti_subtree
, "Recommendation #%d", i
+1);
1337 proto_tree_add_item_ret_length(subtree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1339 proto_tree_add_item(subtree
, hf_slsk_ranking
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1341 proto_item_set_len(ti_subtree
, offset
-start_offset
);
1343 break; /* invalid format */
1350 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1351 /* Client-to-Server */
1352 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1353 "Get User Recommendations (Code: %02d)", msg_code
);
1355 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1358 else if (check_slsk_format(tvb
, pinfo
, offset
, "isi*")) {
1359 /* Server-to-Client */
1360 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1361 "Get User Recommendations Reply (Code: %02d)", msg_code
);
1363 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1365 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_recommendations
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1367 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1369 for (i
= 0; i
< j
; i
++) {
1370 if (check_slsk_format(tvb
, pinfo
, offset
, "s*")) {
1371 start_offset
= offset
;
1372 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 1, ett_slsk_recommendation
, &ti_subtree
, "Recommendation #%d", i
+1);
1373 proto_tree_add_item_ret_length(subtree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1375 proto_item_set_len(ti_subtree
, offset
-start_offset
);
1377 break; /* invalid format */
1384 if (check_slsk_format(tvb
, pinfo
, offset
, "isi*")) {
1385 /* Client-to-Server */
1386 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1387 "Admin Command (Code: %02d)", msg_code
);
1389 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_string
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1391 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_strings
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1393 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1395 for (i
= 0; i
< j
; i
++) {
1396 if (check_slsk_format(tvb
, pinfo
, offset
, "s*")) {
1397 start_offset
= offset
;
1398 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 1, ett_slsk_string
, &ti_subtree
, "String #%d", i
+1);
1399 proto_tree_add_item_ret_length(subtree
, hf_slsk_string
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1401 proto_item_set_len(ti_subtree
, offset
-start_offset
);
1403 break; /* invalid format */
1410 if (check_slsk_format(tvb
, pinfo
, offset
, "isii")) {
1411 /* Client-to-Server & Server-to-Client */
1412 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1413 "Place In Line Response (Code: %02d)", msg_code
);
1415 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1417 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1419 proto_tree_add_item(slsk_tree
, hf_slsk_place_in_queue
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1425 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1426 /* Server-to-Client */
1427 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1428 "Room Added (Code: %02d)", msg_code
);
1430 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1436 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1437 /* Server-to-Client */
1438 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1439 "Room Removed (Code: %02d)", msg_code
);
1441 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1447 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
1448 /* Client-to-Server */
1449 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1450 "Room List Request (Code: %02d)", msg_code
);
1453 else if (check_slsk_format(tvb
, pinfo
, offset
, "ii*")) {
1454 /* Server-to-Client */
1455 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1456 "Room List (Code: %02d)", msg_code
);
1458 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_number_of_rooms
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1460 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1462 for (i
= 0; i
< j
; i
++) {
1463 if (check_slsk_format(tvb
, pinfo
, offset
, "s*")) {
1464 start_offset
= offset
;
1465 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 1, ett_slsk_room
, &ti_subtree
, "Room #%d", i
+1);
1466 proto_tree_add_item_ret_length(subtree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1468 proto_item_set_len(ti_subtree
, offset
-start_offset
);
1470 break; /* invalid format */
1473 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
1474 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_users_in_room
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1476 for (i
= 0; i
< j
; i
++) {
1477 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
1478 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 4, ett_slsk_room
, &ti_subtree
, "Room #%d", i
+1);
1479 proto_tree_add_item(subtree
, hf_slsk_users_in_room
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1482 break; /* invalid format */
1490 if (check_slsk_format(tvb
, pinfo
, offset
, "isissiii")) {
1491 /* Server-to-Client */
1492 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1493 "Exact File Search (Code: %02d)", msg_code
);
1495 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1497 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1499 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1501 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_directory
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1503 proto_tree_add_item(slsk_tree
, hf_slsk_bytes
, tvb
, offset
, 16, ENC_NA
);
1506 else if (check_slsk_format(tvb
, pinfo
, offset
, "iissiiib")) {
1507 /* Client-to-Server */
1508 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1509 "Exact File Search (Code: %02d)", msg_code
);
1511 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1513 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_filename
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1515 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_directory
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1517 proto_tree_add_item(slsk_tree
, hf_slsk_bytes
, tvb
, offset
, 13, ENC_NA
);
1523 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1524 /* Server-to-Client */
1525 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1526 "Admin Message (Code: %02d)", msg_code
);
1528 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_chat_message
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1534 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
1535 /* Client-to-Server */
1536 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1537 "Global User List Request (Code: %02d)", msg_code
);
1540 else if (check_slsk_format(tvb
, pinfo
, offset
, "isi*")) { /* same as case 14 */
1541 /* Server-to-Client */
1542 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1543 "Global User List (Code: %02d)", msg_code
);
1545 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_room
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1547 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_users_in_room
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1549 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1551 for (i
= 0; i
< j
; i
++) {
1552 if (check_slsk_format(tvb
, pinfo
, offset
, "s*")) {
1553 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_user
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1556 break; /* invalid format */
1559 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
1560 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_users_in_room
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1562 for (i
= 0; i
< j
; i
++) {
1563 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
1564 proto_tree_add_item(slsk_tree
, hf_slsk_status_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1567 break; /* invalid format */
1571 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
1572 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_users_in_room
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1574 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1576 for (i
= 0; i
< j
; i
++) {
1577 if (check_slsk_format(tvb
, pinfo
, offset
, "iiiii*")) {
1578 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 20, ett_slsk_user
, NULL
, "User #%d", i
+1);
1579 proto_tree_add_item(subtree
, hf_slsk_average_speed
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1581 proto_tree_add_item(subtree
, hf_slsk_download_number
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1583 proto_tree_add_item(subtree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1585 proto_tree_add_item(subtree
, hf_slsk_files
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1587 proto_tree_add_item(subtree
, hf_slsk_directories
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1590 break; /* invalid format */
1594 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
1595 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_slotsfull_records
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1597 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1599 for (i
= 0; i
< j
; i
++) {
1600 if (check_slsk_format(tvb
, pinfo
, offset
, "i*")) {
1601 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 4, ett_slsk_user
, NULL
, "User #%d", i
+1);
1602 proto_tree_add_item(subtree
, hf_slsk_slotsfull
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1605 break; /* invalid format */
1613 if (check_slsk_format(tvb
, pinfo
, offset
, "isiiiis")) {
1614 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1615 "Tunneled Message (Code: %02d)", msg_code
);
1617 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1619 proto_tree_add_item(slsk_tree
, hf_slsk_code
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1621 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1623 proto_tree_add_item(slsk_tree
, hf_slsk_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1625 proto_tree_add_item(slsk_tree
, hf_slsk_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1627 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_chat_message
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1633 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
1634 /* Client-to-Server */
1635 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1636 "Privileged User List Request (Code: %02d)", msg_code
);
1639 else if (check_slsk_format(tvb
, pinfo
, offset
, "ii*")) {
1640 /* Server-to-Client */
1641 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1642 "Privileged User List (Code: %02d)", msg_code
);
1644 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_number_of_priv_users
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1646 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1648 for (i
= 0; i
< j
; i
++) {
1649 if (check_slsk_format(tvb
, pinfo
, offset
, "s*")) {
1650 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_user
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1653 break; /* invalid format */
1660 if (check_slsk_format(tvb
, pinfo
, offset
, "ib")) {
1661 /* Client-to-Server */
1662 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1663 "Get Parent List (Code: %02d)", msg_code
);
1665 proto_tree_add_item(slsk_tree
, hf_slsk_byte
, tvb
, offset
, 1, ENC_NA
);
1671 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1672 /* Client-to-Server */
1673 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1674 "Type 73 (Code: %02d)", msg_code
);
1676 proto_tree_add_item(slsk_tree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1682 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1683 /* Server-to-Client */
1684 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1685 "Parent Min Speed (Code: %02d)", msg_code
);
1687 proto_tree_add_item(slsk_tree
, hf_slsk_parent_min_speed
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1693 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1694 /* Server-to-Client */
1695 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1696 "Parent Speed Connection Ratio (Code: %02d)", msg_code
);
1698 proto_tree_add_item(slsk_tree
, hf_slsk_parent_speed_connection_ratio
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1704 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1705 /* Server-to-Client */
1706 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1707 "Parent Inactivity Before Disconnect (Code: %02d)", msg_code
);
1709 proto_tree_add_item(slsk_tree
, hf_slsk_seconds_parent_inactivity_before_disconnect
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1715 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1716 /* Server-to-Client */
1717 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1718 "Server Inactivity Before Disconnect (Code: %02d)", msg_code
);
1720 proto_tree_add_item(slsk_tree
, hf_slsk_seconds_server_inactivity_before_disconnect
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1726 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1727 /* Server-to-Client */
1728 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1729 "Nodes In Cache Before Disconnect (Code: %02d)", msg_code
);
1731 proto_tree_add_item(slsk_tree
, hf_slsk_nodes_in_cache_before_disconnect
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1737 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1738 /* Server-to-Client */
1739 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1740 "Seconds Before Ping Children (Code: %02d)", msg_code
);
1742 proto_tree_add_item(slsk_tree
, hf_slsk_seconds_before_ping_children
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1748 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1749 /* Server-to-Client */
1750 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1751 "Add To Privileged (Code: %02d)", msg_code
);
1753 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1759 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
1760 /* Client-to-Server */
1761 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1762 "Check Privileges (Code: %02d)", msg_code
);
1765 else if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1766 /* Server-to-Client */
1767 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1768 "Check Privileges Reply (Code: %02d)", msg_code
);
1770 proto_tree_add_item(slsk_tree
, hf_slsk_number_of_days
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1776 if (check_slsk_format(tvb
, pinfo
, offset
, "ibisis")) {
1777 /* Server-to-Client */
1778 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1779 "Embedded Message (Code: %02d)", msg_code
);
1781 if ( tvb_get_uint8(tvb
, offset
) == 3 ){
1782 /* Client-to-Client */
1783 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_embedded_message_type
, tvb
, offset
, 1, msg_code
,
1784 "Distributed Search (Byte: %d)", 3);
1786 proto_tree_add_item(slsk_tree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1788 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1790 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1792 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_search_text
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1799 if (check_slsk_format(tvb
, pinfo
, offset
, "ib")) {
1800 /* Client-to-Server */
1801 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1802 "Become Parent (Code: %02d)", msg_code
);
1804 proto_tree_add_item(slsk_tree
, hf_slsk_byte
, tvb
, offset
, 1, ENC_NA
);
1810 if (check_slsk_format(tvb
, pinfo
, offset
, "ii*")) {
1811 /* Server-to-Client */
1812 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1813 "Random Parent Addresses (Code: %02d)", msg_code
);
1815 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_parent_address
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1817 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1819 for (i
= 0; i
< j
; i
++) {
1820 if (check_slsk_format(tvb
, pinfo
, offset
, "sii*")) {
1822 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_user
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1824 proto_tree_add_item(slsk_tree
, hf_slsk_ip
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1826 proto_tree_add_item(slsk_tree
, hf_slsk_port
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1829 break; /* invalid format */
1836 if (check_slsk_format(tvb
, pinfo
, offset
, "iis")) {
1837 /* Server-to-Client */
1838 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1839 "Send Wishlist Entry (Code: %02d)", msg_code
);
1841 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1843 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_search_text
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1849 if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1850 /* Server-to-Client */
1851 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1852 "Type 104 (Code: %02d)", msg_code
);
1854 proto_tree_add_item(slsk_tree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1860 if (check_slsk_format(tvb
, pinfo
, offset
, "i")) {
1861 /* Client-to-Server */
1862 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1863 "Get Similar Users (Code: %02d)", msg_code
);
1866 else if (check_slsk_format(tvb
, pinfo
, offset
, "ii*")) {
1867 /* Server-to-Client */
1868 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1869 "Get Similar Users Reply (Code: %02d)", msg_code
);
1871 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_number_of_users
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1873 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1875 for (i
= 0; i
< j
; i
++) {
1876 if (check_slsk_format(tvb
, pinfo
, offset
, "si*")) {
1877 start_offset
= offset
;
1878 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 4, ett_slsk_user
, &ti_subtree
, "User #%d", i
+1);
1879 proto_tree_add_item_ret_length(subtree
, hf_slsk_user
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1881 proto_tree_add_item(subtree
, hf_slsk_same_recommendation
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1883 proto_item_set_len(ti_subtree
, offset
-start_offset
);
1885 break; /* invalid format */
1892 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1893 /* Client-to-Server */
1894 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1895 "Get Recommendations for Item (Code: %02d)", msg_code
);
1897 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1900 else if (check_slsk_format(tvb
, pinfo
, offset
, "isi*")) {
1901 /* Server-to-Client */
1902 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1903 "Get Recommendations for Item Reply (Code: %02d)", msg_code
);
1905 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1907 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_recommendations
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1909 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1911 for (i
= 0; i
< j
; i
++) {
1912 if (check_slsk_format(tvb
, pinfo
, offset
, "si*")) {
1913 start_offset
= offset
;
1914 subtree
= proto_tree_add_subtree_format(slsk_tree
, tvb
, offset
, 1, ett_slsk_recommendation
, &ti_subtree
, "Recommendation #%d", i
+1);
1915 proto_tree_add_item_ret_length(subtree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1917 proto_tree_add_item(subtree
, hf_slsk_ranking
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1919 proto_item_set_len(ti_subtree
, offset
-start_offset
);
1921 break; /* invalid format */
1928 if (check_slsk_format(tvb
, pinfo
, offset
, "is")) {
1929 /* Client-to-Server */
1930 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1931 "Get Similar Users for Item (Code: %02d)", msg_code
);
1933 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1936 else if (check_slsk_format(tvb
, pinfo
, offset
, "isi*")) {
1937 /* Server-to-Client */
1938 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1939 "Get Similar Users for Item Reply (Code: %02d)", msg_code
);
1941 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_recommendation
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1943 proto_tree_add_item_ret_int(slsk_tree
, hf_slsk_num_recommendations
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &j
);
1945 if (j
> tvb_reported_length_remaining(tvb
, offset
))
1947 for (i
= 0; i
< j
; i
++) {
1948 if (check_slsk_format(tvb
, pinfo
, offset
, "s*")) {
1949 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1952 break; /* invalid format */
1959 if (check_slsk_format(tvb
, pinfo
, offset
, "iis")) {
1960 /* Client-to-Server */
1961 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1962 "Can't Connect To Peer (Code: %02d)", msg_code
);
1964 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1966 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1969 else if (check_slsk_format(tvb
, pinfo
, offset
, "ii")) {
1970 /* Server-to-Client */
1971 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
1972 "Can't Connect To Peer (Code: %02d)", msg_code
);
1974 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1980 if (check_slsk_format(tvb
, pinfo
, offset
, "bisis")) {
1981 if ( tvb_get_uint8(tvb
, offset
) == 3 ){
1982 /* Client-to-Client */
1983 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 1, msg_code
,
1984 "Distributed Search (Byte: %d)", 3);
1986 proto_tree_add_item(slsk_tree
, hf_slsk_integer
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1988 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1990 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
1992 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_search_text
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
1996 else if (check_slsk_format(tvb
, pinfo
, offset
, "bssi")) {
1997 if ( tvb_get_uint8(tvb
, offset
) == 1 ){
1998 /* Client-to-Client */
2001 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 1, msg_code
,
2002 "Peer Init (Byte: %d)", 1);
2004 proto_tree_add_item_ret_length(slsk_tree
, hf_slsk_username
, tvb
, offset
, 4, ENC_ASCII
|ENC_LITTLE_ENDIAN
, &str_len
);
2006 len
= tvb_get_letohl(tvb
, offset
);
2007 str
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+4, len
, ENC_ASCII
);
2008 proto_tree_add_string_format_value(slsk_tree
, hf_slsk_connection_type
, tvb
, offset
, 4+len
, str
,
2009 "%s (Char: %s)", connection_type(str
),
2010 format_text(pinfo
->pool
, str
, len
));
2012 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2016 else if (check_slsk_format(tvb
, pinfo
, offset
, "bi")) {
2017 if ( tvb_get_uint8(tvb
, offset
) == 0 ){
2018 /* Client-to-Client */
2019 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 1, msg_code
,
2020 "Pierce Fw (Byte: %d)", 0);
2022 proto_tree_add_item(slsk_tree
, hf_slsk_token
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
);
2027 proto_tree_add_uint_format_value(slsk_tree
, hf_slsk_message_code
, tvb
, offset
, 4, msg_code
,
2028 "Unknown (Code: %02d)", msg_code
);
2035 if(offset
< (int)msg_len
){
2036 expert_add_info(pinfo
, ti_len
, &ei_slsk_unknown_data
);
2039 return tvb_captured_length(tvb
);
2043 static int dissect_slsk(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
2045 tcp_dissect_pdus(tvb
, pinfo
, tree
, slsk_desegment
, 4, get_slsk_pdu_len
, dissect_slsk_pdu
, data
);
2046 return tvb_captured_length(tvb
);
2050 /* Register the protocol with Wireshark */
2053 proto_register_slsk(void)
2056 /* Setup list of header fields */
2057 static hf_register_info hf
[] = {
2059 { "Integer", "slsk.integer",
2060 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2062 { "String", "slsk.string",
2063 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2065 { "Byte", "slsk.byte",
2066 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2067 { &hf_slsk_message_length
,
2068 { "Message Length", "slsk.message.length",
2069 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2070 { &hf_slsk_message_code
,
2071 { "Message Type", "slsk.message.code",
2072 FT_UINT32
, BASE_DEC
, NULL
, 0, "Message Code with type string", HFILL
} },
2073 { &hf_slsk_embedded_message_type
,
2074 { "Embedded Message Type", "slsk.embedded_message.code",
2075 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2076 { &hf_slsk_client_ip
,
2077 { "Client IP", "slsk.client.ip",
2078 FT_IPv4
, BASE_NONE
, NULL
, 0, "Client IP Address", HFILL
} },
2080 { &hf_slsk_server_ip
,
2081 { "SoulSeek Server IP", "slsk.server.ip",
2082 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2084 { &hf_slsk_directory_name
,
2085 { "Directory name", "slsk.directory_name",
2086 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2087 { &hf_slsk_username
,
2088 { "Username", "slsk.username",
2089 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2090 { &hf_slsk_password
,
2091 { "Password", "slsk.password",
2092 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2094 { "Version", "slsk.version",
2095 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2096 { &hf_slsk_login_successful
,
2097 { "Login successful", "slsk.login.successful",
2098 FT_UINT8
, BASE_DEC
, VALS(slsk_yes_no
), 0, NULL
, HFILL
} },
2099 { &hf_slsk_login_message
,
2100 { "Login Message", "slsk.login.message",
2101 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2103 { "Port Number", "slsk.port.number",
2104 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2106 { "IP Address", "slsk.ip.address",
2107 FT_IPv4
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2108 { &hf_slsk_user_exists
,
2109 { "User exists", "slsk.user.exists",
2110 FT_UINT8
, BASE_DEC
, VALS(slsk_yes_no
), 0, NULL
, HFILL
} },
2111 { &hf_slsk_status_code
,
2112 { "Status Code", "slsk.status.code",
2113 FT_UINT32
, BASE_DEC
, VALS(slsk_status_codes
), 0, NULL
, HFILL
} },
2115 { "Room", "slsk.room",
2116 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2117 { &hf_slsk_chat_message
,
2118 { "Chat Message", "slsk.chat.message",
2119 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2120 { &hf_slsk_users_in_room
,
2121 { "Users in Room", "slsk.room.users",
2122 FT_INT32
, BASE_DEC
, NULL
, 0, "Number of Users in Room", HFILL
} },
2124 { "Token", "slsk.token",
2125 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2126 { &hf_slsk_connection_type
,
2127 { "Connection Type", "slsk.connection.type",
2128 FT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2129 { &hf_slsk_chat_message_id
,
2130 { "Chat Message ID", "slsk.chat.message.id",
2131 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2132 { &hf_slsk_timestamp
,
2133 { "Timestamp", "slsk.timestamp",
2134 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2135 { &hf_slsk_search_text
,
2136 { "Search Text", "slsk.search.text",
2137 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2138 { &hf_slsk_folder_count
,
2139 { "Folder Count", "slsk.folder.count",
2140 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2141 { &hf_slsk_file_count
,
2142 { "File Count", "slsk.file.count",
2143 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2144 { &hf_slsk_average_speed
,
2145 { "Average Speed", "slsk.average.speed",
2146 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2147 { &hf_slsk_download_number
,
2148 { "Download Number", "slsk.download.number",
2149 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2151 { "Files", "slsk.files",
2152 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2153 { &hf_slsk_directories
,
2154 { "Directories", "slsk.directories",
2155 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2156 { &hf_slsk_slotsfull
,
2157 { "Slots full", "slsk.slots.full",
2158 FT_UINT32
, BASE_DEC
, NULL
, 0, "Upload Slots Full", HFILL
} },
2159 { &hf_slsk_place_in_queue
,
2160 { "Place in Queue", "slsk.queue.place",
2161 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2162 { &hf_slsk_number_of_rooms
,
2163 { "Number of Rooms", "slsk.room.count",
2164 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2165 { &hf_slsk_filename
,
2166 { "Filename", "slsk.filename",
2167 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2168 { &hf_slsk_filename_ext
,
2169 { "Filename ext", "slsk.filename_ext",
2170 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2171 { &hf_slsk_directory
,
2172 { "Directory", "slsk.directory",
2173 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2175 { "Size", "slsk.size",
2176 FT_UINT32
, BASE_DEC
, NULL
, 0, "File Size", HFILL
} },
2178 { &hf_slsk_checksum
,
2179 { "Checksum", "slsk.checksum",
2180 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2183 { "Code", "slsk.code",
2184 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2185 { &hf_slsk_number_of_users
,
2186 { "Number of Users", "slsk.user.count",
2187 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2188 { &hf_slsk_number_of_days
,
2189 { "Number of Days", "slsk.day.count",
2190 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2191 { &hf_slsk_transfer_direction
,
2192 { "Transfer Direction", "slsk.transfer.direction",
2193 FT_INT32
, BASE_DEC
, VALS(slsk_transfer_direction
), 0, NULL
, HFILL
} },
2194 { &hf_slsk_user_description
,
2195 { "User Description", "slsk.user.description",
2196 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2197 { &hf_slsk_picture_exists
,
2198 { "Picture exists", "slsk.user.picture.exists",
2199 FT_UINT8
, BASE_DEC
, VALS(slsk_yes_no
), 0, "User has a picture", HFILL
} },
2201 { "User Picture", "slsk.user.picture",
2202 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2204 { &hf_slsk_user_uploads
,
2205 { "User uploads", "slsk.uploads.user",
2206 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2208 { &hf_slsk_total_uploads
,
2209 { "Total uploads allowed", "slsk.uploads.total",
2210 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2211 { &hf_slsk_queued_uploads
,
2212 { "Queued uploads", "slsk.uploads.queued",
2213 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2214 { &hf_slsk_slots_available
,
2215 { "Upload Slots available", "slsk.uploads.available",
2216 FT_UINT8
, BASE_DEC
, VALS(slsk_yes_no
), 0, NULL
, HFILL
} },
2218 { "Download allowed", "slsk.user.allowed",
2219 FT_UINT8
, BASE_DEC
, VALS(slsk_yes_no
), 0, NULL
, HFILL
} },
2220 { &hf_slsk_compr_packet
,
2221 { "zlib compressed packet", "slsk.compr.packet",
2222 FT_NONE
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2223 { &hf_slsk_parent_min_speed
,
2224 { "Parent Min Speed", "slsk.parent.min.speed",
2225 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2226 { &hf_slsk_parent_speed_connection_ratio
,
2227 { "Parent Speed Connection Ratio", "slsk.parent.speed.connection.ratio",
2228 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2229 { &hf_slsk_seconds_parent_inactivity_before_disconnect
,
2230 { "Seconds Parent Inactivity Before Disconnect", "slsk.seconds.parent.inactivity.before.disconnect",
2231 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2232 { &hf_slsk_seconds_server_inactivity_before_disconnect
,
2233 { "Seconds Server Inactivity Before Disconnect", "slsk.seconds.server.inactivity.before.disconnect",
2234 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2235 { &hf_slsk_nodes_in_cache_before_disconnect
,
2236 { "Nodes In Cache Before Disconnect", "slsk.nodes.in.cache.before.disconnect",
2237 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2238 { &hf_slsk_seconds_before_ping_children
,
2239 { "Seconds Before Ping Children", "slsk.seconds.before.ping.children",
2240 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2241 { &hf_slsk_recommendation
,
2242 { "Recommendation", "slsk.recommendation",
2243 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2245 { "User", "slsk.user",
2246 FT_UINT_STRING
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2248 { "Ranking", "slsk.ranking",
2249 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2250 { &hf_slsk_compressed_packet_length
,
2251 { "Compressed packet length", "slsk.compressed_packet_length",
2252 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2253 { &hf_slsk_uncompressed_packet_length
,
2254 { "Uncompressed packet length", "slsk.uncompressed_packet_length",
2255 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2256 { &hf_slsk_num_directories
,
2257 { "Number of directories", "slsk.num_directories",
2258 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2259 { &hf_slsk_upload_speed
,
2260 { "Upload speed", "slsk.upload_speed",
2261 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2262 { &hf_slsk_in_queue
,
2263 { "In Queue", "slsk.in_queue",
2264 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2265 { &hf_slsk_num_slotsfull_records
,
2266 { "Number of Slotsfull Records", "slsk.num_slotsfull_records",
2267 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2268 { &hf_slsk_num_recommendations
,
2269 { "Number of Recommendations", "slsk.num_recommendations",
2270 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2271 { &hf_slsk_num_files
,
2272 { "Number of Files", "slsk.num_files",
2273 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2274 { &hf_slsk_num_strings
,
2275 { "Number of strings", "slsk.num_strings",
2276 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2277 { &hf_slsk_file_code
,
2278 { "Code", "slsk.file_code",
2279 FT_UINT8
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2280 { &hf_slsk_file_size1
,
2281 { "Size1", "slsk.file_size1",
2282 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2283 { &hf_slsk_file_size2
,
2284 { "Size2", "slsk.file_size2",
2285 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2286 { &hf_slsk_file_num_attributes
,
2287 { "Number of attributes", "slsk.file_num_attributes",
2288 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2289 { &hf_slsk_file_attribute_type
,
2290 { "File attribute type", "slsk.file_attribute_type",
2291 FT_UINT32
, BASE_DEC
, VALS(slsk_attr_type
), 0, NULL
, HFILL
} },
2292 { &hf_slsk_file_attribute_value
,
2293 { "File attribute value", "slsk.file_attribute_value",
2294 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2295 { &hf_slsk_free_upload_slots
,
2296 { "Free upload slots", "slsk.free_upload_slots",
2297 FT_UINT32
, BASE_DEC
, VALS(slsk_yes_no
), 0, NULL
, HFILL
} },
2299 { "Bytes", "slsk.bytes",
2300 FT_BYTES
, BASE_NONE
, NULL
, 0, NULL
, HFILL
} },
2301 { &hf_slsk_same_recommendation
,
2302 { "Same Recommendation", "slsk.same_recommendation",
2303 FT_UINT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2304 { &hf_slsk_number_of_priv_users
,
2305 { "Number of Privileged Users", "slsk.priv_user.count",
2306 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2307 { &hf_slsk_num_parent_address
,
2308 { "Number of Parent Addresses", "slsk.parent_addr.count",
2309 FT_INT32
, BASE_DEC
, NULL
, 0, NULL
, HFILL
} },
2313 /* Setup protocol subtree array */
2314 static int *ett
[] = {
2316 &ett_slsk_compr_packet
,
2317 &ett_slsk_directory
,
2319 &ett_slsk_file_attribute
,
2321 &ett_slsk_recommendation
,
2326 static ei_register_info ei
[] = {
2327 { &ei_slsk_unknown_data
, { "slsk.unknown_data", PI_UNDECODED
, PI_WARN
, "Unknown Data (not interpreted)", EXPFILL
}},
2328 { &ei_slsk_zlib_decompression_failed
, { "slsk.zlib_decompression_failed", PI_PROTOCOL
, PI_WARN
, "zlib compressed packet failed to decompress", EXPFILL
}},
2329 { &ei_slsk_decompression_failed
, { "slsk.decompression_failed", PI_PROTOCOL
, PI_WARN
, "decompression failed", EXPFILL
}},
2332 module_t
*slsk_module
;
2333 expert_module_t
* expert_slsk
;
2335 /* Registers the protocol name and description */
2336 proto_slsk
= proto_register_protocol("SoulSeek Protocol", "SoulSeek", "slsk");
2338 /* Required function calls to register the header fields and subtrees used */
2339 proto_register_field_array(proto_slsk
, hf
, array_length(hf
));
2340 proto_register_subtree_array(ett
, array_length(ett
));
2341 expert_slsk
= expert_register_protocol(proto_slsk
);
2342 expert_register_field_array(expert_slsk
, ei
, array_length(ei
));
2344 /* Register the dissector handle */
2345 slsk_handle
= register_dissector("slsk", dissect_slsk
, proto_slsk
);
2347 /* Registers the options in the menu preferences */
2348 slsk_module
= prefs_register_protocol(proto_slsk
, NULL
);
2349 prefs_register_bool_preference(slsk_module
, "desegment",
2350 "Reassemble SoulSeek messages spanning multiple TCP segments",
2351 "Whether the SoulSeek dissector should reassemble messages spanning multiple TCP segments."
2352 " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2354 #if defined (HAVE_ZLIB) || defined (HAVE_ZLIBNG)
2355 prefs_register_bool_preference(slsk_module
, "decompress",
2356 "Decompress zlib compressed packets inside SoulSeek messages",
2357 "Whether the SoulSeek dissector should decompress all zlib compressed packets inside messages",
2365 proto_reg_handoff_slsk(void)
2367 dissector_add_uint_range_with_preference("tcp.port", SLSK_TCP_PORT_RANGE
, slsk_handle
);
2371 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2376 * indent-tabs-mode: nil
2379 * ex: set shiftwidth=2 tabstop=8 expandtab:
2380 * :indentSize=2:tabSize=8:noTabs=true: