Don't guard col_set_str (COL_INFO) with col_check
[metze/wireshark/wip.git] / epan / dissectors / packet-slsk.c
1 /* packet-slsk.c
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
7  *
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
11  *
12  * $Id$
13  *
14  * Wireshark - Network traffic analyzer
15  * By Gerald Combs <gerald@wireshark.org>
16  * Copyright 1998 Gerald Combs
17  *
18  * This program is free software; you can redistribute it and/or
19  * modify it under the terms of the GNU General Public License
20  * as published by the Free Software Foundation; either version 2
21  * of the License, or (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41 #include <glib.h>
42
43 #include <epan/packet.h>
44 #include <epan/tvbuff.h>
45 #include "packet-tcp.h"
46 #include <epan/prefs.h>
47 #include <epan/strutil.h>
48
49 /* Initialize the protocol and registered fields */
50 static int proto_slsk = -1;
51
52 static int hf_slsk_integer = -1;
53 static int hf_slsk_string = -1;
54 static int hf_slsk_byte = -1;
55 static int hf_slsk_message_length = -1;
56 static int hf_slsk_message_code = -1;
57 static int hf_slsk_client_ip = -1;
58 static int hf_slsk_server_ip = -1;
59 static int hf_slsk_string_length = -1;
60 static int hf_slsk_username = -1;
61 static int hf_slsk_password = -1;
62 static int hf_slsk_version = -1;
63 static int hf_slsk_login_successful = -1;
64 static int hf_slsk_login_message = -1;
65 static int hf_slsk_port = -1;
66 static int hf_slsk_ip = -1;
67 static int hf_slsk_user_exists = -1;
68 static int hf_slsk_status_code = -1;
69 static int hf_slsk_room = -1;
70 static int hf_slsk_chat_message = -1;
71 static int hf_slsk_users_in_room = -1;
72 static int hf_slsk_token = -1;
73 static int hf_slsk_connection_type = -1;
74 static int hf_slsk_chat_message_id = -1;
75 static int hf_slsk_timestamp = -1;
76 static int hf_slsk_search_text = -1;
77 static int hf_slsk_folder_count = -1;
78 static int hf_slsk_file_count = -1;
79 static int hf_slsk_average_speed = -1;
80 static int hf_slsk_download_number = -1;
81 static int hf_slsk_files = -1;
82 static int hf_slsk_directories = -1;
83 static int hf_slsk_slotsfull = -1;
84 static int hf_slsk_place_in_queue = -1;
85 static int hf_slsk_number_of_rooms = -1;
86 static int hf_slsk_filename = -1;
87 static int hf_slsk_directory = -1;
88 static int hf_slsk_size = -1;
89 static int hf_slsk_checksum = -1;
90 static int hf_slsk_code = -1;
91 static int hf_slsk_number_of_users = -1;
92 static int hf_slsk_number_of_days = -1;
93 static int hf_slsk_transfer_direction = -1;
94 static int hf_slsk_user_description = -1;
95 static int hf_slsk_picture_exists = -1;
96 static int hf_slsk_picture = -1;
97 static int hf_slsk_user_uploads = -1;
98 static int hf_slsk_total_uploads = -1;
99 static int hf_slsk_queued_uploads = -1;
100 static int hf_slsk_slots_available = -1;
101 static int hf_slsk_allowed = -1;
102 static int hf_slsk_compr_packet = -1;
103 static int hf_slsk_parent_min_speed = -1;
104 static int hf_slsk_parent_speed_connection_ratio = -1;
105 static int hf_slsk_seconds_parent_inactivity_before_disconnect = -1;
106 static int hf_slsk_seconds_server_inactivity_before_disconnect = -1;
107 static int hf_slsk_nodes_in_cache_before_disconnect = -1;
108 static int hf_slsk_seconds_before_ping_children = -1;
109 static int hf_slsk_recommendation = -1;
110 static int hf_slsk_ranking = -1;
111
112
113 /* Initialize the subtree pointers */
114 static gint ett_slsk = -1;
115 static gint ett_slsk_compr_packet = -1;
116
117 #define TCP_PORT_SLSK_1                         2234
118 #define TCP_PORT_SLSK_2                         5534
119 #define TCP_PORT_SLSK_3                         2240
120
121
122 /* desegmentation of SoulSeek Message over TCP */
123 static gboolean slsk_desegment = TRUE;
124 #ifdef HAVE_LIBZ
125 static gboolean slsk_decompress = TRUE;
126 #else
127 static gboolean slsk_decompress = FALSE;
128 #endif
129
130 static const value_string slsk_tcp_msgs[] = {
131         { 1, "Login"},
132         { 2, "Set Wait Port"},
133         { 3, "Get Peer Address"},
134         { 4, "Get Shared File List"},
135         { 5, "User Exists / Shared File List"},
136         { 7, "Get User Status"},
137         { 9, "File Search Result"},
138         { 13, "Say ChatRoom"},
139         { 14, "Join Room"},
140         { 15, "Leave Room / User Info Request"},
141         { 16, "User Joined Room / User Info Reply"},
142         { 17, "User Left Room"},
143         { 18, "Connect To Peer"},
144         { 22, "Message User"},
145         { 23, "Message User Ack"},
146         { 26, "File Search"},
147         { 28, "Set Status"},
148         { 32, "Ping"},
149         { 34, "Update Upload Speed"},
150         { 35, "Shared Files & Folders"},
151         { 36, "Get User Stats / Folder Contents Request"},
152         { 37, "Folder Contents Response"},
153         { 40, "Queued Downloads / Transfer Request"},
154         { 41, "Transfer Response"},
155         { 42, "Placehold Upload"},
156         { 43, "Queue Upload"},
157         { 44, "Place In Queue"},
158         { 46, "Upload Failed"},
159         { 50, "Queue Failed / Own Recommendation"},
160         { 51, "Add Things I like / Place In Queue Request"},
161         { 52, "Remove Things I like"},
162         { 54, "Get Recommendations"},
163         { 55, "Type 55"},
164         { 56, "Get Global Rankings"},
165         { 57, "Get User Recommendations"},
166         { 58, "Admin Command"},
167         { 60, "Place In Line Response"},
168         { 62, "Room Added"},
169         { 63, "Room Removed"},
170         { 64, "Room List"},
171         { 65, "Exact File Search"},
172         { 66, "Admin Message"},
173         { 67, "Global User List"},
174         { 68, "Tunneled Message"},
175         { 69, "Privileged User List"},
176         { 71, "Get Parent List"},
177         { 73, "Type 73"},
178         { 83, "Parent Min Speed"},
179         { 84, "Parent Speed Connection Ratio"},
180         { 86, "Parent Inactivity Before Disconnect"},
181         { 87, "Server Inactivity Before Disconnect"},
182         { 88, "Nodes In Cache Before Disconnect"},
183         { 90, "Seconds Before Ping Children"},
184         { 91, "Add To Privileged"},
185         { 92, "Check Privileges"},
186         { 93, "Embedded Message"},
187         { 100, "Become Parent"},
188         { 102, "Random Parent Addresses"},
189         { 103, "Send Wishlist Entry"},
190         { 104, "Type 104"},
191         { 110, "Get Similar Users"},
192         { 111, "Get Recommendations for Item"},
193         { 112, "Get Similar Users for Item"},
194         { 1001, "Can't Connect To Peer"},
195         { 0, NULL }
196 };
197
198 static const value_string slsk_status_codes[] = {
199         { -1, "Unknown"},
200         { 0, "Offline"},
201         { 1, "Away"},
202         { 2, "Online"},
203         { 0, NULL }
204 };
205
206 static const value_string slsk_transfer_direction[] = {
207         { 0, "Download"},
208         { 1, "Upload"},
209         { 0, NULL }
210 };
211
212 static const value_string slsk_yes_no[] = {
213         { 0, "No"},
214         { 1, "Yes"},
215         { 0, NULL }
216 };
217
218 static const value_string slsk_attr_type[] = {
219         { 0, "Bitrate"},
220         { 1, "Length"},
221         { 2, "VBR"},
222         { 0, NULL }
223 };
224
225 static const char* connection_type(char con_type[]) {
226         if (strlen(con_type) != 1) return "Unknown";
227         if (con_type[0] == 'D') return "Distributed Search";
228         if (con_type[0] == 'P') return "Peer Connection";               /* "File Search Result / User Info Request / Get Shared File List" */
229         if (con_type[0] == 'F') return "File Transfer";
230         return "Unknown";
231 }
232
233 static gboolean check_slsk_format(tvbuff_t *tvb, int offset, const char format[]){
234
235         /*
236         * Returns TRUE if tvbuff beginning at offset matches a certain format
237         * The format is given by an array of characters standing for a special field type
238         *               i - integer     (4 bytes)
239         *               b - byte        (1 byte)
240         *               s - string      (string_length + 4 bytes)
241         *
242         *               * - can be used at the end of a format to ignore any following bytes
243         */
244
245         switch ( format[0] ) {
246                 case 'i':
247                         if (tvb_length_remaining(tvb, offset) < 4) return FALSE;
248                         offset += 4;
249                 break;
250                 case 'b':
251                         if (tvb_length_remaining(tvb, offset) < 1) return FALSE;
252                         offset += 1;
253                 break;
254                 case 's':
255                         if (tvb_length_remaining(tvb, offset) < 4) return FALSE;
256                         if (tvb_length_remaining(tvb, offset) < (int)tvb_get_letohl(tvb, offset)+4) return FALSE;
257                         offset += tvb_get_letohl(tvb, offset)+4;
258                 break;
259                 case '*':
260                         return TRUE;
261                 default:
262                         return FALSE;
263         }
264
265         if (format[1] == '\0' ) {
266                 if (tvb_length_remaining(tvb, offset) != 0) return FALSE;       /* Checks for additional bytes at the end */
267                         return TRUE;
268         }
269         return check_slsk_format(tvb, offset, &format[1]);
270
271 }
272
273 static const char* get_message_type(tvbuff_t *tvb) {
274         /*
275         * Checks if the Message Code is known.
276         * If unknown checks if the Message Code is stored in a byte.
277         * Returns the Message Type.
278         */
279         int msg_code = tvb_get_letohl(tvb, 4);
280         const gchar *message_type =  match_strval(msg_code, slsk_tcp_msgs);
281         if (message_type == NULL) {
282                 if (check_slsk_format(tvb, 4, "bisis"))
283                         message_type = "Distributed Search";
284                 else if (check_slsk_format(tvb, 4, "bssi"))
285                         message_type = "Peer Init";
286                 else if (check_slsk_format(tvb, 4, "bi"))
287                         message_type = "Pierce Fw";
288                 else
289                         message_type = "Unknown";
290         }
291         return message_type;
292 }
293
294 static guint get_slsk_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
295 {
296         guint32 msg_len;
297         msg_len = tvb_get_letohl(tvb, offset);
298         /* That length doesn't include the length field itself; add that in. */
299         msg_len += 4;
300         return msg_len;
301 }
302
303 /* Code to actually dissect the packets */
304
305 static void dissect_slsk_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
306 {
307
308 /* Set up structures needed to add the protocol subtree and manage it */
309         proto_item *ti;
310         proto_tree *slsk_tree;
311
312         int offset, i, j;
313         guint32 msg_len, msg_code;
314         const gchar *message_type;
315         guint8 *str;
316
317         int comprlen = 0;
318         int uncomprlen = 0;
319         int uncompr_tvb_offset = 0;
320         int i2 = 0;
321         int j2 = 0;
322         int i3 = 0;
323         int j3 = 0;
324
325         offset = 0;
326
327         msg_len = tvb_get_letohl(tvb, offset);
328         msg_code = tvb_get_letohl(tvb, offset+4);
329         message_type =  get_message_type(tvb);
330
331 /* Make entries in Protocol column and Info column on summary display */
332         col_set_str(pinfo->cinfo, COL_PROTOCOL, "slsk");
333
334 /* This field shows up as the "Info" column in the display  */
335
336         col_set_str(pinfo->cinfo, COL_INFO, "SoulSeek Message");
337
338         if (check_col(pinfo->cinfo, COL_INFO)) {
339             col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", message_type);
340         }
341
342
343         if (tree) {
344
345 /* create display subtree for the protocol */
346                 ti = proto_tree_add_item(tree, proto_slsk, tvb, 0, -1, FALSE);
347                 slsk_tree = proto_item_add_subtree(ti, ett_slsk);
348
349 /* Continue adding tree items to process the packet here */
350
351                 proto_tree_add_uint(slsk_tree, hf_slsk_message_length, tvb, offset, 4, msg_len);
352                 offset += 4;
353
354                 switch (msg_code) {
355
356                         case  1:
357                                 if (check_slsk_format(tvb, offset, "issi")) {
358                                         /* Client-to-Server */
359                                         message_type = "Login";
360                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
361                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
362                                         offset += 4;
363                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
364                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
365                                         offset += 4+tvb_get_letohl(tvb, offset);
366                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
367                                         proto_tree_add_item(slsk_tree, hf_slsk_password, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
368                                         offset += 4+tvb_get_letohl(tvb, offset);
369                                         proto_tree_add_uint(slsk_tree, hf_slsk_version, tvb, offset, 4, tvb_get_letohl(tvb, offset));
370                                         offset += 4;
371                                 }
372                                 else if (check_slsk_format(tvb, offset, "ibs") || check_slsk_format(tvb, offset, "ibsi")) {
373                                         /* Server-to-Client */
374                                         message_type = "Login Reply";
375                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
376                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
377                                         offset += 4;
378                                         i=tvb_get_guint8(tvb, offset);
379                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_login_successful, tvb, offset, 1, tvb_get_guint8(tvb, offset),
380                                                 "Login successful: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
381                                         offset += 1;
382                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
383                                         proto_tree_add_item(slsk_tree, hf_slsk_login_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
384                                         offset += 4+tvb_get_letohl(tvb, offset);
385                                         if (i == 1){
386                                                 proto_tree_add_ipv4(slsk_tree, hf_slsk_client_ip, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
387                                                 offset += 4;
388                                         }
389                                 }
390                         break;
391
392                         case  2:
393                                 if (check_slsk_format(tvb, offset, "ii")) {
394                                         /* Client-to-Server */
395                                         message_type = "Set Wait Port";
396                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
397                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
398                                         offset += 4;
399                                         proto_tree_add_uint(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset));
400                                         offset += 4;
401                                 }
402                         break;
403
404                         case  3:
405                                 if (check_slsk_format(tvb, offset, "isii")) {
406                                         /* Server-to-Client */
407                                         message_type = "Get Peer Address Reply";
408                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
409                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
410                                         offset += 4;
411                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
412                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
413                                         offset += 4+tvb_get_letohl(tvb, offset);
414                                         proto_tree_add_ipv4(slsk_tree, hf_slsk_ip, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
415                                         offset += 4;
416                                         proto_tree_add_uint(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset));
417                                         offset += 4;
418                                 }
419                                 else if (check_slsk_format(tvb, offset, "is")) {
420                                         /* Client-to-Server */
421                                         message_type = "Get Peer Address";
422                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
423                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
424                                         offset += 4;
425                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
426                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
427                                         offset += 4+tvb_get_letohl(tvb, offset);
428                                 }
429                         break;
430
431                         case 4:
432                                 if (check_slsk_format(tvb, offset, "i")) {
433                                         /* Client-to-Client */
434                                         message_type = "Get Shared File List";
435                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
436                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
437                                         offset += 4;
438                                 }
439                         break;
440
441                         case  5:
442                                 if (check_slsk_format(tvb, offset, "isb")) {
443                                         /* Server-to-Client */
444                                         message_type = "User Exists Reply";
445                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
446                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
447                                         offset += 4;
448                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
449                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
450                                         offset += 4+tvb_get_letohl(tvb, offset);
451                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_user_exists, tvb, offset, 1, tvb_get_guint8(tvb, offset),
452                                                 "User exists: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
453                                         offset += 1;
454                                 }
455                                 else if (check_slsk_format(tvb, offset, "is")) {
456                                         /* Client-to-Server */
457                                         message_type = "User Exists Request";
458                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
459                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
460                                         offset += 4;
461                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
462                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
463                                         offset += 4+tvb_get_letohl(tvb, offset);
464                                 }
465                                 else if (check_slsk_format(tvb, offset, "i*")) {
466                                         /* Client-to-Client */
467                                         message_type = "Shared File List";
468                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
469                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
470                                         offset += 4;
471
472                                         /* [zlib compressed] */
473                                         comprlen = tvb_length_remaining(tvb, offset);
474
475                                         if (slsk_decompress == TRUE){
476
477                                                 tvbuff_t *uncompr_tvb = tvb_child_uncompress(tvb, tvb, offset, comprlen);
478
479                                                 if (uncompr_tvb == NULL) {
480                                                         proto_tree_add_text(slsk_tree, tvb, offset, -1,
481                                                                 "[zlib compressed packet]");
482                                                         offset += tvb_length_remaining(tvb, offset);
483                                                         proto_tree_add_text(slsk_tree, tvb, 0, 0,
484                                                                 "(uncompression failed !)");
485                                                 } else {
486
487                                                         proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, FALSE);
488                                                         proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
489
490                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
491                                                                 "(  compressed packet length: %d)", comprlen);
492                                                         uncomprlen = tvb_reported_length_remaining(uncompr_tvb, 0);
493                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
494                                                                 "(uncompressed packet length: %d)", uncomprlen);
495
496                                                         add_new_data_source(pinfo, uncompr_tvb,
497                                                             "Uncompressed SoulSeek data");
498                                                         uncompr_tvb_offset = 0;
499                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "i*")) {
500                                                                 i=0;
501                                                                 j = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
502                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, uncompr_tvb_offset, 4, j,
503                                                                         "Number of directories: %u", j);
504                                                                 uncompr_tvb_offset += 4;
505                                                                 while (i<j){
506                                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "si*")) {
507                                                                                 guint32 len;
508
509                                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
510                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb,
511                                                                                         uncompr_tvb_offset, 4, len,
512                                                                                         "Directory #%d String Length: %u", i+1, len);
513                                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb, uncompr_tvb_offset+4, len,
514                                                                                         "Directory #%d Name: %s", i+1,
515                                                                                         tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
516                                                                                 uncompr_tvb_offset += 4+len;
517                                                                                 i2=0;
518                                                                                 j2 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
519                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb,
520                                                                                         uncompr_tvb_offset, 4, j2,
521                                                                                         "Directory #%d Number of files: %u", i+1, j2);
522                                                                                 uncompr_tvb_offset += 4;
523                                                                                 while (i2<j2){
524                                                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
525                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_byte, uncompr_tvb,
526                                                                                                         uncompr_tvb_offset, 1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset),
527                                                                                                         "Dir #%d File #%d Code: %d", i+1, i2+1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset));
528                                                                                                 uncompr_tvb_offset += 1;
529                                                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
530                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length,
531                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, len,
532                                                                                                         "Dir #%d File #%d String Length: %u", i+1, i2+1, len);
533                                                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb,
534                                                                                                         uncompr_tvb_offset+4, len,
535                                                                                                         "Dir #%d File #%d Filename: %s", i+1, i2+1,
536                                                                                                         tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
537                                                                                                 uncompr_tvb_offset += 4+len;
538                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer,
539                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4,
540                                                                                                         tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
541                                                                                                         "Dir #%d File #%d Size1: %u", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
542                                                                                                 uncompr_tvb_offset += 4;
543                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer,
544                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4,
545                                                                                                         tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
546                                                                                                         "Dir #%d File #%d Size2: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
547                                                                                                 uncompr_tvb_offset += 4;
548                                                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
549                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length,
550                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, len,
551                                                                                                         "Dir #%d File #%d String Length: %u", i+1, i2+1, len);
552                                                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb,
553                                                                                                         uncompr_tvb_offset+4, len,
554                                                                                                         "Dir #%d File #%d ext: %s", i+1, i2+1,
555                                                                                                         tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
556                                                                                                 uncompr_tvb_offset += 4+len;
557                                                                                                 i3=0;
558                                                                                                 j3 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
559                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer,
560                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4,
561                                                                                                         tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
562                                                                                                         "Dir #%d File #%d Number of attributes: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
563                                                                                                 uncompr_tvb_offset += 4;
564                                                                                                 while (i3<j3){
565                                                                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
566                                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree,
567                                                                                                                         hf_slsk_integer, uncompr_tvb,
568                                                                                                                         uncompr_tvb_offset, 4,
569                                                                                                                         tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
570                                                                                                                         "Dir #%d File #%d Attr #%d type: %s (Code: %d)", i+1, i2+1, i3+1, val_to_str(tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset), slsk_attr_type, "Unknown"), tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
571                                                                                                                 uncompr_tvb_offset += 4;
572                                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree,
573                                                                                                                         hf_slsk_integer, uncompr_tvb,
574                                                                                                                         uncompr_tvb_offset, 4,
575                                                                                                                         tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
576                                                                                                                         "Dir #%d File #%d Attr #%d value: %d", i+1, i2+1, i3+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
577                                                                                                                 uncompr_tvb_offset += 4;
578                                                                                                                 i3++;
579                                                                                                         }
580                                                                                                 }
581                                                                                         }
582                                                                                         i2++;
583                                                                                 }
584                                                                         }
585                                                                         i++;
586                                                                 }
587                                                         }
588                                                 }
589                                         }else {
590                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
591                                                         "[zlib compressed packet]");
592                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 0, 0,
593                                                         "(  compressed packet length: %d)", comprlen);
594                                                 offset += tvb_length_remaining(tvb, offset);
595                                         }
596                                 }
597                         break;
598
599                         case  7:
600                                 if (check_slsk_format(tvb, offset, "isi")) {
601                                         /* Server-to-Client */
602                                         message_type = "Get User Status Reply";
603                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
604                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
605                                         offset += 4;
606                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
607                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
608                                         offset += 4+tvb_get_letohl(tvb, offset);
609                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_status_code, tvb, offset, 4, tvb_get_letohl(tvb, offset),
610                                                 "Status: %s (Code: %d)", val_to_str(tvb_get_letohl(tvb, offset), slsk_status_codes, "Unknown"), tvb_get_letohl(tvb, offset));
611                                         offset += 4;
612                                 }
613                                 else if (check_slsk_format(tvb, offset, "is")) {
614                                         /* Client-to-Server */
615                                         message_type = "Get User Status";
616                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
617                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
618                                         offset += 4;
619                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
620                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
621                                         offset += 4+tvb_get_letohl(tvb, offset);
622                                 }
623                         break;
624
625                         case 9:
626                                 if (check_slsk_format(tvb, offset, "i*")) {
627                                         /* Client-to-Client */
628                                         message_type = "File Search Result";
629                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
630                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
631                                         offset += 4;
632
633                                         /* [zlib compressed] */
634                                         comprlen = tvb_length_remaining(tvb, offset);
635
636                                         if (slsk_decompress == TRUE){
637
638                                                 tvbuff_t *uncompr_tvb = tvb_child_uncompress(tvb, tvb, offset, comprlen);
639
640                                                 if (uncompr_tvb == NULL) {
641                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, tvb_length_remaining(tvb, offset), 0,
642                                                                 "[zlib compressed packet]");
643                                                         offset += tvb_length_remaining(tvb, offset);
644                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, 0, 0, 0,
645                                                                 "(uncompression failed !)");
646                                                 } else {
647
648                                                         proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, FALSE);
649                                                         proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
650
651                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
652                                                                 "(  compressed packet length: %d)", comprlen);
653                                                         uncomprlen = tvb_length_remaining(uncompr_tvb, 0);
654                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
655                                                                 "(uncompressed packet length: %d)", uncomprlen);
656
657                                                         add_new_data_source(pinfo, uncompr_tvb,
658                                                             "Uncompressed SoulSeek data");
659                                                         uncompr_tvb_offset = 0;
660                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "sii*")) {
661                                                                 guint32 len;
662
663                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
664                                                                 proto_tree_add_uint(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb, uncompr_tvb_offset, 4, len);
665                                                                 proto_tree_add_item(slsk_compr_packet_tree, hf_slsk_username, uncompr_tvb, uncompr_tvb_offset+4, len, TRUE);
666                                                                 uncompr_tvb_offset += 4+len;
667                                                                 proto_tree_add_item(slsk_compr_packet_tree, hf_slsk_token, uncompr_tvb, uncompr_tvb_offset, 4, TRUE);
668                                                                 uncompr_tvb_offset += 4;
669                                                                 i=0; j = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
670                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, uncompr_tvb_offset, 4, j,
671                                                                         "Number of files: %d", j);
672                                                                 uncompr_tvb_offset += 4;
673                                                                 while (i<j){
674                                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
675                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_byte, uncompr_tvb, 0, 0, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset),
676                                                                                         "File #%d Code: %d", i+1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset));
677                                                                                 uncompr_tvb_offset += 1;
678                                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
679                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb,
680                                                                                         uncompr_tvb_offset, 4, len,
681                                                                                         "File #%d String Length: %u", i+1, len);
682                                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb, uncompr_tvb_offset+4, len,
683                                                                                         "File #%d Filename: %s", i+1,
684                                                                                         tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
685                                                                                 uncompr_tvb_offset += 4+len;
686                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb,
687                                                                                         uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
688                                                                                         "File #%d Size1: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
689                                                                                 uncompr_tvb_offset += 4;
690                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb,
691                                                                                         uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
692                                                                                         "File #%d Size2: %d", i+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
693                                                                                 uncompr_tvb_offset += 4;
694                                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
695                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length, uncompr_tvb,
696                                                                                         uncompr_tvb_offset, 4, len,
697                                                                                         "File #%d String Length: %d", i+1, len);
698                                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb, uncompr_tvb_offset+4, len,
699                                                                                         "File #%d ext: %s", i+1,
700                                                                                         tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
701                                                                                 uncompr_tvb_offset += 4+len;
702                                                                                 i2=0;
703                                                                                 j2 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
704                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb,
705                                                                                         uncompr_tvb_offset, 4, j,
706                                                                                         "File #%d Number of attributes: %d", i+1, j);
707                                                                                 uncompr_tvb_offset += 4;
708                                                                                 while (i2<j2){
709                                                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
710                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer,
711                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
712                                                                                                         "File #%d Attr #%d type: %s (Code: %d)", i+1, i2+1, val_to_str(tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset), slsk_attr_type, "Unknown"), tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
713                                                                                                 uncompr_tvb_offset += 4;
714                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer,
715                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
716                                                                                                         "File #%d Attr #%d value: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
717                                                                                                 uncompr_tvb_offset += 4;
718                                                                                         }
719                                                                                         i2++;
720                                                                                 }
721                                                                         }
722                                                                         i++;
723                                                                 }
724                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_byte, uncompr_tvb, uncompr_tvb_offset, 1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset),
725                                                                         "Free upload slots: %s (Byte: %d)", val_to_str(tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset), slsk_yes_no, "Unknown"), tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset));
726                                                                 uncompr_tvb_offset += 1;
727                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
728                                                                         "Upload speed: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
729                                                                 uncompr_tvb_offset += 4;
730                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb, uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
731                                                                         "In Queue: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
732                                                                 uncompr_tvb_offset += 4;
733                                                         }
734                                                 }
735                                         }else {
736                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
737                                                         "[zlib compressed packet]");
738                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
739                                                         "(  compressed packet length: %d)", comprlen);
740                                                 offset += tvb_length_remaining(tvb, offset);
741                                         }
742                                 }
743                         break;
744
745                         case 13:
746                                 if (check_slsk_format(tvb, offset, "isss")) {
747                                         /* Server-to-Client */
748                                         message_type = "Say ChatRoom";
749                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
750                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
751                                         offset += 4;
752                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
753                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
754                                         offset += 4+tvb_get_letohl(tvb, offset);
755                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
756                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
757                                         offset += 4+tvb_get_letohl(tvb, offset);
758                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
759                                         proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
760                                         offset += 4+tvb_get_letohl(tvb, offset);
761                                 }
762                                 else if (check_slsk_format(tvb, offset, "iss")) {
763                                         /* Client-to-Server */
764                                         message_type = "Say ChatRoom";
765                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
766                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
767                                         offset += 4;
768                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
769                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
770                                         offset += 4+tvb_get_letohl(tvb, offset);
771                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
772                                         proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
773                                         offset += 4+tvb_get_letohl(tvb, offset);
774                                 }
775                         break;
776
777                         case 14:
778                                 if (check_slsk_format(tvb, offset, "is")) {
779                                         /* Client-to-Server */
780                                         message_type = "Join/Add Room";
781                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
782                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
783                                         offset += 4;
784                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
785                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
786                                         offset += 4+tvb_get_letohl(tvb, offset);
787                                 }
788                                 else if (check_slsk_format(tvb, offset, "isi*")) {
789                                         /* Server-to-Client */
790                                         message_type = "Join Room User List";
791                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
792                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
793                                         offset += 4;
794                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
795                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
796                                         offset += 4+tvb_get_letohl(tvb, offset);
797                                         i=0; j = tvb_get_letohl(tvb, offset);
798                                         proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
799                                         offset += 4;
800                                         while (i<j){
801                                                 if (check_slsk_format(tvb, offset, "s*")) {
802                                                         guint32 len;
803
804                                                         len = tvb_get_letohl(tvb, offset);
805                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
806                                                                 "String #%d Length: %d", i+1, len);
807                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
808                                                                 "User #%d: %s", i+1, tvb_format_text(tvb, offset+4, len));
809                                                         offset += 4+len;
810                                                 }
811                                                 i++;
812                                         }
813                                         if (check_slsk_format(tvb, offset, "i*")) {
814                                                 i=0; j = tvb_get_letohl(tvb, offset);
815                                                 proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
816                                                 offset += 4;
817                                                 while (i<j){
818                                                         if (check_slsk_format(tvb, offset, "i*")) {
819                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_status_code, tvb, offset, 4, tvb_get_letohl(tvb, offset),
820                                                                         "Status of User #%d: %s (Code: %d)", i+1, val_to_str(tvb_get_letohl(tvb, offset), slsk_status_codes, "Unknown"), tvb_get_letohl(tvb, offset));
821                                                                 offset += 4;
822                                                         }
823                                                         i++;
824                                                 }
825                                         }
826                                         if (check_slsk_format(tvb, offset, "i*")) {
827                                                 i=0; j = tvb_get_letohl(tvb, offset);
828                                                 proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
829                                                 offset += 4;
830                                                 while (i<j){
831                                                         if (check_slsk_format(tvb, offset, "iiiii*")) {
832                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
833                                                                         "Average Speed of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
834                                                                 offset += 4;
835                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
836                                                                         "Downloadnum of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
837                                                                 offset += 4;
838                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
839                                                                         "Something of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
840                                                                 offset += 4;
841                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
842                                                                         "Files of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
843                                                                 offset += 4;
844                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
845                                                                         "Folders of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
846                                                                 offset += 4;
847                                                         }
848                                                         i++;
849                                                 }
850                                         }
851                                         if (check_slsk_format(tvb, offset, "i*")) {
852                                                 i=0; j = tvb_get_letohl(tvb, offset);
853                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
854                                                         "Number of Slotsfull Records: %d", tvb_get_letohl(tvb, offset));
855                                                 offset += 4;
856                                                 while (i<j){
857                                                         if (check_slsk_format(tvb, offset, "i*")) {
858                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
859                                                                         "Slots full of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
860                                                                 offset += 4;
861                                                         }
862                                                         i++;
863                                                 }
864                                         }
865                                 }
866                         break;
867
868                         case 15:
869                                 if (check_slsk_format(tvb, offset, "is")) {
870                                         /* Client-to-Server & Server-to-Client */
871                                         message_type = "Leave Room";
872                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
873                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
874                                         offset += 4;
875                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
876                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
877                                         offset += 4+tvb_get_letohl(tvb, offset);
878                                 }
879                                 else if (check_slsk_format(tvb, offset, "i")) {
880                                         /* Client-to-Client */
881                                         message_type = "User Info Request";
882                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
883                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
884                                         offset += 4;
885                                 }
886                         break;
887
888                         case 16:
889                                 if (check_slsk_format(tvb, offset, "issiiiiiii")) {
890                                         /* Server-to-Client */
891                                         message_type = "User Joined Room";
892                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
893                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
894                                         offset += 4;
895                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
896                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
897                                         offset += 4+tvb_get_letohl(tvb, offset);
898                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
899                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
900                                         offset += 4+tvb_get_letohl(tvb, offset);
901                                         proto_tree_add_uint(slsk_tree, hf_slsk_total_uploads, tvb, offset, 4, tvb_get_letohl(tvb, offset));
902                                         offset += 4;
903                                         proto_tree_add_uint(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, tvb_get_letohl(tvb, offset));
904                                         offset += 4;
905                                         proto_tree_add_uint(slsk_tree, hf_slsk_download_number, tvb, offset, 4, tvb_get_letohl(tvb, offset));
906                                         offset += 4;
907                                         proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
908                                         offset += 4;
909                                         proto_tree_add_uint(slsk_tree, hf_slsk_files, tvb, offset, 4, tvb_get_letohl(tvb, offset));
910                                         offset += 4;
911                                         proto_tree_add_uint(slsk_tree, hf_slsk_directories, tvb, offset, 4, tvb_get_letohl(tvb, offset));
912                                         offset += 4;
913                                         proto_tree_add_uint(slsk_tree, hf_slsk_slotsfull, tvb, offset, 4, tvb_get_letohl(tvb, offset));
914                                         offset += 4;
915                                 }
916                                 else if (check_slsk_format(tvb, offset, "isbiib") || check_slsk_format(tvb, offset, "isbsiib")) {
917                                         /* Client-to-Client */
918                                         message_type = "User Info Reply";
919                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
920                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
921                                         offset += 4;
922                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
923                                         proto_tree_add_item(slsk_tree, hf_slsk_user_description, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
924                                         offset += 4+tvb_get_letohl(tvb, offset);
925                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_picture_exists, tvb, offset, 1, tvb_get_guint8(tvb, offset),
926                                                 "Picture exists: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
927                                         offset += 1;
928                                         if ( tvb_get_guint8(tvb, offset -1 ) == 1 ) {
929                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
930                                                         "Picture Size: %d", tvb_get_letohl(tvb, offset));
931                                                 proto_tree_add_item(slsk_tree, hf_slsk_picture, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
932                                                 offset += 4+tvb_get_letohl(tvb, offset);
933                                         }
934                                         proto_tree_add_uint(slsk_tree, hf_slsk_total_uploads, tvb, offset, 4, tvb_get_letohl(tvb, offset));
935                                         offset += 4;
936                                         proto_tree_add_uint(slsk_tree, hf_slsk_queued_uploads, tvb, offset, 4, tvb_get_letohl(tvb, offset));
937                                         offset += 4;
938                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_slots_available, tvb, offset, 1, tvb_get_guint8(tvb, offset),
939                                                 "Upload Slots available: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
940                                         offset += 1;
941                                 }
942                         break;
943
944                         case 17:
945                                 if (check_slsk_format(tvb, offset, "iss")) {
946                                         /* Server-to-Client */
947                                         message_type = "User Left Room";
948                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
949                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
950                                         offset += 4;
951                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
952                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
953                                         offset += 4+tvb_get_letohl(tvb, offset);
954                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
955                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
956                                         offset += 4+tvb_get_letohl(tvb, offset);
957                                 }
958                         break;
959
960                         case 18:
961                                 if (check_slsk_format(tvb, offset, "iiss")) {
962                                         /* Client-to-Server */
963                                         guint32 len;
964
965                                         message_type = "Connect To Peer";
966                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
967                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
968                                         offset += 4;
969                                         proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, TRUE);
970                                         offset += 4;
971                                         len = tvb_get_letohl(tvb, offset);
972                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len);
973                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, len, FALSE);
974                                         offset += 4+len;
975                                         len = tvb_get_letohl(tvb, offset);
976                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len);
977                                         str = tvb_get_ephemeral_string(tvb, offset+4, len);
978                                         proto_tree_add_string_format(slsk_tree, hf_slsk_connection_type, tvb, offset+4, len, str,
979                                                 "Connection Type: %s (Char: %s)", connection_type(str),
980                                                 format_text(str, len));
981                                         offset += 4+len;
982                                 }
983                                 else if (check_slsk_format(tvb, offset, "issiii")) {
984                                         /* Server-to-Client */
985                                         guint32 len;
986
987                                         message_type = "Connect To Peer";
988                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
989                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
990                                         offset += 4;
991                                         len = tvb_get_letohl(tvb, offset);
992                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len);
993                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, len, FALSE);
994                                         offset += 4+len;
995                                         len = tvb_get_letohl(tvb, offset);
996                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len);
997                                         str = tvb_get_ephemeral_string(tvb, offset+4, len);
998                                         proto_tree_add_string_format(slsk_tree, hf_slsk_connection_type, tvb, offset+4, len, str,
999                                                 "Connection Type: %s (Char: %s)", connection_type(str),
1000                                                 format_text(str, len));
1001                                         offset += 4+len;
1002                                         proto_tree_add_item(slsk_tree, hf_slsk_ip, tvb, offset, 4, FALSE);
1003                                         offset += 4;
1004                                         proto_tree_add_item(slsk_tree, hf_slsk_port, tvb, offset, 4, TRUE);
1005                                         offset += 4;
1006                                         proto_tree_add_item(slsk_tree, hf_slsk_token, tvb, offset, 4, TRUE);
1007                                         offset += 4;
1008                                 }
1009                         break;
1010
1011                         case 22:
1012                                 if (check_slsk_format(tvb, offset, "iss")) {
1013                                         /* Client-to-Server */
1014                                         message_type = "Message User Send";
1015                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1016                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1017                                         offset += 4;
1018                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1019                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1020                                         offset += 4+tvb_get_letohl(tvb, offset);
1021                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1022                                         proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1023                                         offset += 4+tvb_get_letohl(tvb, offset);
1024                                 }
1025                                 else if (check_slsk_format(tvb, offset, "iiiss")) {
1026                                         /* Server-to-Client */
1027                                         message_type = "Message User Receive";
1028                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1029                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1030                                         offset += 4;
1031                                         proto_tree_add_uint(slsk_tree, hf_slsk_chat_message_id, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1032                                         offset += 4;
1033                                         proto_tree_add_uint(slsk_tree, hf_slsk_timestamp, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1034                                         offset += 4;
1035                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1036                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1037                                         offset += 4+tvb_get_letohl(tvb, offset);
1038                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1039                                         proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1040                                         offset += 4+tvb_get_letohl(tvb, offset);
1041                                 }
1042                         break;
1043
1044                         case 23:
1045                                 if (check_slsk_format(tvb, offset, "ii")) {
1046                                         /* Client-to-Server */
1047                                         message_type = "Message User Receive Ack";
1048                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1049                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1050                                         offset += 4;
1051                                         proto_tree_add_uint(slsk_tree, hf_slsk_chat_message_id, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1052                                         offset += 4;
1053                                 }
1054                         break;
1055
1056                         case 26:
1057                                 if (check_slsk_format(tvb, offset, "iis")) {
1058                                         /* Client-to-Server */
1059                                         message_type = "File Search";
1060                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1061                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1062                                         offset += 4;
1063                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1064                                         offset += 4;
1065                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1066                                         proto_tree_add_item(slsk_tree, hf_slsk_search_text, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1067                                         offset += 4+tvb_get_letohl(tvb, offset);
1068                                 }
1069                         break;
1070
1071                         case 28:
1072                                 if (check_slsk_format(tvb, offset, "ii")) {
1073                                         /* Client-to-Server */
1074                                         message_type = "Set Status";
1075                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1076                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1077                                         offset += 4;
1078                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_status_code, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1079                                                 "Status: %s (Code: %d)", val_to_str(tvb_get_letohl(tvb, offset), slsk_status_codes, "Unknown"), tvb_get_letohl(tvb, offset));
1080                                         offset += 4;
1081                                 }
1082                         break;
1083
1084                         case 32:
1085                                 if (check_slsk_format(tvb, offset, "i")) {
1086                                         /* Client-to-Server */
1087                                         message_type = "Ping";
1088                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1089                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1090                                         offset += 4;
1091                                 }
1092                         break;
1093
1094                         case 34:
1095                                 if (check_slsk_format(tvb, offset, "isi")) {
1096                                         /* Client-to-Server */
1097                                         message_type = "Update Upload Speed";
1098                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1099                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1100                                         offset += 4;
1101                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1102                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1103                                         offset += 4+tvb_get_letohl(tvb, offset);
1104                                         proto_tree_add_uint(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1105                                         offset += 4;
1106                                 }
1107                         break;
1108
1109                         case 35:
1110                                 if (check_slsk_format(tvb, offset, "iii")) {
1111                                         /* Client-to-Server */
1112                                         message_type = "Shared Files & Folders ";
1113                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1114                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1115                                         offset += 4;
1116                                         proto_tree_add_uint(slsk_tree, hf_slsk_folder_count, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1117                                         offset += 4;
1118                                         proto_tree_add_uint(slsk_tree, hf_slsk_file_count, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1119                                         offset += 4;
1120                                 }
1121                         break;
1122
1123                         case 36:
1124                                 if (check_slsk_format(tvb, offset, "isiiiii")) {
1125                                         /* Server-to-Client */
1126                                         message_type = "Get User Stats Reply";
1127                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1128                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1129                                         offset += 4;
1130                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1131                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1132                                         offset += 4+tvb_get_letohl(tvb, offset);
1133                                         proto_tree_add_uint(slsk_tree, hf_slsk_average_speed, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1134                                         offset += 4;
1135                                         proto_tree_add_uint(slsk_tree, hf_slsk_download_number, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1136                                         offset += 4;
1137                                         proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1138                                         offset += 4;
1139                                         proto_tree_add_uint(slsk_tree, hf_slsk_files, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1140                                         offset += 4;
1141                                         proto_tree_add_uint(slsk_tree, hf_slsk_directories, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1142                                         offset += 4;
1143                                 }
1144                                 else if (check_slsk_format(tvb, offset, "is")) {
1145                                         /* Client-to-Client */
1146                                         /* Client-to-Server: send after login successful */
1147                                         message_type = "Get User Stats";
1148                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1149                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1150                                         offset += 4;
1151                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1152                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1153                                         offset += 4+tvb_get_letohl(tvb, offset);
1154                                 }
1155                                 else if (check_slsk_format(tvb, offset, "iis")) {
1156                                         /* Client-to-Client */
1157                                         message_type = "Folder Contents Request";
1158                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1159                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1160                                         offset += 4;
1161                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1162                                         offset += 4;
1163                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1164                                         proto_tree_add_item(slsk_tree, hf_slsk_directory, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1165                                         offset += 4+tvb_get_letohl(tvb, offset);
1166                                 }
1167                         break;
1168
1169                         case 37:
1170                                 if (check_slsk_format(tvb, offset, "i*")) {
1171                                         /* Client-to-Client */
1172                                         message_type = "Folder Contents Response";
1173                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1174                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1175                                         offset += 4;
1176
1177                                         /* [zlib compressed] */
1178                                         comprlen = tvb_length_remaining(tvb, offset);
1179
1180                                         if (slsk_decompress == TRUE){
1181
1182                                                 tvbuff_t *uncompr_tvb = tvb_child_uncompress(tvb, tvb, offset, comprlen);
1183
1184                                                 if (uncompr_tvb == NULL) {
1185                                                         proto_tree_add_text(slsk_tree, tvb, offset, -1,
1186                                                                 "[zlib compressed packet]");
1187                                                         offset += tvb_length_remaining(tvb, offset);
1188                                                         proto_tree_add_text(slsk_tree, tvb, 0, 0,
1189                                                                 "[uncompression failed !]");
1190                                                 } else {
1191
1192                                                         proto_item *ti2 = proto_tree_add_item(slsk_tree, hf_slsk_compr_packet, tvb, offset, -1, FALSE);
1193                                                         proto_tree *slsk_compr_packet_tree = proto_item_add_subtree(ti2, ett_slsk_compr_packet);
1194
1195                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
1196                                                                 "[compressed packet length: %d]", comprlen);
1197                                                         uncomprlen = tvb_length_remaining(uncompr_tvb, 0);
1198                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
1199                                                                 "[uncompressed packet length: %d]", uncomprlen);
1200
1201                                                         add_new_data_source(pinfo, uncompr_tvb,
1202                                                             "Uncompressed SoulSeek data");
1203                                                         uncompr_tvb_offset = 0;
1204                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "isi*")) {
1205                                                                 guint32 len;
1206
1207                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb,
1208                                                                         uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
1209                                                                         "Token: %d", tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
1210                                                                 uncompr_tvb_offset += 4;
1211                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
1212                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length,
1213                                                                         uncompr_tvb, uncompr_tvb_offset, 4, len,
1214                                                                         "Directory Name String Length: %u", len);
1215                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb, uncompr_tvb_offset+4, len,
1216                                                                         "Directory Name: %s", tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
1217                                                                 uncompr_tvb_offset += 4+len;
1218
1219                                                                 i=0; j = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
1220                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb,
1221                                                                         uncompr_tvb_offset, 4, j,
1222                                                                         "Number of directories: %d", j);
1223                                                                 uncompr_tvb_offset += 4;
1224                                                                 while (i<j){
1225                                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "si*")) {
1226                                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
1227                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length,
1228                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, len,
1229                                                                                         "Directory #%d Name String Length: %u", i+1, len);
1230                                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb, uncompr_tvb_offset+4, len,
1231                                                                                         "Directory #%d Name: %s", i+1,
1232                                                                                         tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
1233                                                                                 uncompr_tvb_offset += 4+len;
1234                                                                                 i2 = 0;
1235                                                                                 j2 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
1236                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb,
1237                                                                                         uncompr_tvb_offset, 4, j2,
1238                                                                                         "Directory #%d Number of files: %d", i+1, j2);
1239                                                                                 uncompr_tvb_offset += 4;
1240                                                                                 while (i2<j2){
1241                                                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "bsiisi*")) {
1242                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_byte,
1243                                                                                                         uncompr_tvb, uncompr_tvb_offset, 1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset),
1244                                                                                                         "Dir #%d File #%d Code: %d", i+1, i2+1, tvb_get_guint8(uncompr_tvb, uncompr_tvb_offset));
1245                                                                                                 uncompr_tvb_offset += 1;
1246                                                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
1247                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length,
1248                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, len,
1249                                                                                                         "Dir #%d File #%d String Length: %d", i+1, i2+1, len);
1250                                                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb,
1251                                                                                                         uncompr_tvb_offset+4, len,
1252                                                                                                         "Dir #%d File #%d Filename: %s", i+1, i2+1,
1253                                                                                                         tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
1254                                                                                                 uncompr_tvb_offset += 4+len;
1255                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer,
1256                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
1257                                                                                                         "Dir #%d File #%d Size1: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
1258                                                                                                 uncompr_tvb_offset += 4;
1259                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer,
1260                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
1261                                                                                                         "Dir #%d File #%d Size2: %d", i+1, i2+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
1262                                                                                                 uncompr_tvb_offset += 4;
1263                                                                                                 len = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
1264                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_string_length,
1265                                                                                                         uncompr_tvb, uncompr_tvb_offset, 4, len,
1266                                                                                                         "Dir #%d File #%d String Length: %d", i+1, i2+1, len);
1267                                                                                                 proto_tree_add_text(slsk_compr_packet_tree, uncompr_tvb,
1268                                                                                                         uncompr_tvb_offset+4, len,
1269                                                                                                         "Dir #%d File #%d ext: %s", i+1, i2+1,
1270                                                                                                         tvb_format_text(uncompr_tvb, uncompr_tvb_offset+4, len));
1271                                                                                                 uncompr_tvb_offset += 4+len;
1272                                                                                                 i3 = 0;
1273                                                                                                 j3 = tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset);
1274                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree, hf_slsk_integer, uncompr_tvb,
1275                                                                                                         uncompr_tvb_offset, 4, j3,
1276                                                                                                         "Dir #%d File #%d Number of attributes: %d", i+1, i2+1, j3);
1277                                                                                                 uncompr_tvb_offset += 4;
1278                                                                                                 while (i3<j3){
1279                                                                                                         if (check_slsk_format(uncompr_tvb, uncompr_tvb_offset, "ii*")) {
1280                                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree,
1281                                                                                                                         hf_slsk_integer, uncompr_tvb,
1282                                                                                                                         uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
1283                                                                                                                         "Dir #%d File #%d Attr #%d type: %s (Code: %d)", i+1, i2+1, i3+1, val_to_str(tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset), slsk_attr_type, "Unknown"), tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
1284                                                                                                                 uncompr_tvb_offset += 4;
1285                                                                                                                 proto_tree_add_uint_format(slsk_compr_packet_tree,
1286                                                                                                                         hf_slsk_integer, uncompr_tvb,
1287                                                                                                                         uncompr_tvb_offset, 4, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset),
1288                                                                                                                         "Dir #%d File #%d Attr #%d value: %d", i+1, i2+1, i3+1, tvb_get_letohl(uncompr_tvb, uncompr_tvb_offset));
1289                                                                                                                 uncompr_tvb_offset += 4;
1290                                                                                                         }
1291                                                                                                         i3++;
1292                                                                                                 }
1293                                                                                         }
1294                                                                                         i2++;
1295                                                                                 }
1296                                                                         }
1297                                                                         i++;
1298                                                                 }
1299                                                         }
1300                                                 }
1301                                         }else {
1302                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
1303                                                         "[zlib compressed packet]");
1304                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, -1, 0,
1305                                                         "(  compressed packet length: %d)", comprlen);
1306                                                 offset += tvb_length_remaining(tvb, offset);
1307                                         }
1308                                 }
1309                         break;
1310
1311                         case 40:
1312                                 if (check_slsk_format(tvb, offset, "isi")) {
1313                                         /* Server-to-Client */
1314                                         message_type = "Queued Downloads";
1315                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1316                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1317                                         offset += 4;
1318                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1319                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1320                                         offset += 4+tvb_get_letohl(tvb, offset);
1321                                         proto_tree_add_uint(slsk_tree, hf_slsk_slotsfull, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1322                                         offset += 4;
1323                                 }
1324                                 else if (check_slsk_format(tvb, offset, "iiis") || check_slsk_format(tvb, offset, "iiisii")) {
1325                                         /* Client-to-Client */
1326                                         message_type = "Transfer Request";
1327                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1328                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1329                                         offset += 4;
1330                                         i = tvb_get_letohl(tvb, offset);
1331                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_transfer_direction, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1332                                                 "Transfer Direction: %s (Code: %d)", val_to_str(tvb_get_letohl(tvb, offset), slsk_transfer_direction, "Unknown"), tvb_get_letohl(tvb, offset));
1333                                         offset += 4;
1334                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1335                                         offset += 4;
1336                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1337                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1338                                         offset += 4+tvb_get_letohl(tvb, offset);
1339                                         if (i == 1){
1340                                                 proto_tree_add_uint(slsk_tree, hf_slsk_size, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1341                                                 offset += 4;
1342                                                 proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1343                                                 offset += 4;
1344                                         }
1345                                 }
1346
1347                         break;
1348
1349                         case 41:
1350                                 if (check_slsk_format(tvb, offset, "iibs") || check_slsk_format(tvb, offset, "iibii") || check_slsk_format(tvb, offset, "iib")) {
1351                                         /* Client-to-Client */
1352                                         message_type = "Transfer Response";
1353                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1354                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1355                                         offset += 4;
1356                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1357                                         offset += 4;
1358                                         i = tvb_get_guint8(tvb, offset);
1359                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_allowed, tvb, offset, 1, tvb_get_guint8(tvb, offset),
1360                                                 "Download allowed: %s (Byte: %d)", val_to_str(tvb_get_guint8(tvb, offset), slsk_yes_no, "Unknown"), tvb_get_guint8(tvb, offset));
1361                                         offset += 1;
1362                                         if ( i == 1 ) {
1363                                                 if ( tvb_length_remaining(tvb, offset) == 8 ) {
1364                                                         proto_tree_add_uint(slsk_tree, hf_slsk_size, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1365                                                         offset += 4;
1366                                                         proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1367                                                         offset += 4;
1368                                                 }
1369                                         } else {
1370                                                 proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1371                                                 proto_tree_add_item(slsk_tree, hf_slsk_string, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1372                                                 offset += 4+tvb_get_letohl(tvb, offset);
1373                                         }
1374                                 }
1375                         break;
1376
1377                         case 42:
1378                                 if (check_slsk_format(tvb, offset, "is")) {
1379                                         /* Client-to-Client */
1380                                         message_type = "Placehold Upload";
1381                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1382                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1383                                         offset += 4;
1384                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1385                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1386                                         offset += 4+tvb_get_letohl(tvb, offset);
1387                                 }
1388                         break;
1389
1390                         case 43:
1391                                 if (check_slsk_format(tvb, offset, "is")) {
1392                                         /* Client-to-Client */
1393                                         message_type = "Queue Upload";
1394                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1395                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1396                                         offset += 4;
1397                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1398                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1399                                         offset += 4+tvb_get_letohl(tvb, offset);
1400                                 }
1401                         break;
1402
1403                         case 44:
1404                                 if (check_slsk_format(tvb, offset, "isi")) {
1405                                         /* Client-to-Client */
1406                                         message_type = "Place In Queue";
1407                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1408                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1409                                         offset += 4;
1410                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1411                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1412                                         offset += 4+tvb_get_letohl(tvb, offset);
1413                                         proto_tree_add_uint(slsk_tree, hf_slsk_place_in_queue, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1414                                         offset += 4;
1415                                 }
1416                         break;
1417
1418                         case 46:
1419                                 if (check_slsk_format(tvb, offset, "is")) {
1420                                         /* Client-to-Client */
1421                                         message_type = "Upload Failed";
1422                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1423                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1424                                         offset += 4;
1425                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1426                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1427                                         offset += 4+tvb_get_letohl(tvb, offset);
1428                                 }
1429                         break;
1430
1431                         case 50:
1432                                 if (check_slsk_format(tvb, offset, "is")) {
1433                                         /* Client-to-Server */
1434                                         message_type = "Make Own Recommendation";
1435                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1436                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1437                                         offset += 4;
1438                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1439                                         proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1440                                         offset += 4+tvb_get_letohl(tvb, offset);
1441                                 }
1442                                 else if (check_slsk_format(tvb, offset, "isi")) {
1443                                         /* Client-to-Server */
1444                                         message_type = "Remove Own Recommendation";
1445                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1446                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1447                                         offset += 4;
1448                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1449                                         proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1450                                         offset += 4+tvb_get_letohl(tvb, offset);
1451                                         proto_tree_add_uint(slsk_tree, hf_slsk_ranking, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1452                                         offset += 4;
1453                                 }
1454                                 else if (check_slsk_format(tvb, offset, "iss")) {
1455                                         /* Client-to-Client */
1456                                         message_type = "Queue Failed";
1457                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1458                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1459                                         offset += 4;
1460                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1461                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1462                                         offset += 4+tvb_get_letohl(tvb, offset);
1463                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1464                                         proto_tree_add_item(slsk_tree, hf_slsk_string, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1465                                         offset += 4+tvb_get_letohl(tvb, offset);
1466                                 }
1467                         break;
1468
1469                         case 51:
1470                                 if (check_slsk_format(tvb, offset, "is")) {
1471                                         /* Client-to-Server: "Add Things I like" */
1472                                         /* Client-to-Client:  "Place In Queue Request" */
1473                                         message_type = "Add Things I like / Place In Queue Request";
1474                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1475                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1476                                         offset += 4;
1477                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1478                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1479                                         offset += 4+tvb_get_letohl(tvb, offset);
1480                                 }
1481                         break;
1482
1483                         case 52:
1484                                 if (check_slsk_format(tvb, offset, "is")) {
1485                                         /* Client-to-Server */
1486                                         message_type = "Remove Things I like";
1487                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1488                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1489                                         offset += 4;
1490                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1491                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1492                                         offset += 4+tvb_get_letohl(tvb, offset);
1493                                 }
1494                         break;
1495
1496                         case 54:
1497                                 if (check_slsk_format(tvb, offset, "i")) {
1498                                         /* Client-to-Server */
1499                                         message_type = "Get Recommendations";
1500                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1501                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1502                                         offset += 4;
1503                                 }
1504                                 else if (check_slsk_format(tvb, offset, "ii*")) {
1505                                         /* Server-to-Client */
1506                                         message_type = "Get Recommendations Reply";
1507                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1508                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1509                                         offset += 4;
1510                                         i=0; j = tvb_get_letohl(tvb, offset);
1511                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1512                                                 "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
1513                                         offset += 4;
1514                                         while (i<j){
1515                                                 if (check_slsk_format(tvb, offset, "si*")) {
1516                                                         guint32 len;
1517
1518                                                         len = tvb_get_letohl(tvb, offset);
1519                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
1520                                                                 "String #%d Length: %d", i+1, len);
1521                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
1522                                                                 "Recommendation #%d: %s", i+1,
1523                                                                 tvb_format_text(tvb, offset+4, len));
1524                                                         offset += 4+len;
1525                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_ranking, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1526                                                                 "Ranking #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1527                                                         offset += 4;
1528                                                 }
1529                                                 i++;
1530                                         }
1531                                 }
1532                         break;
1533
1534                         case 55:
1535                                 if (check_slsk_format(tvb, offset, "i")) {
1536                                         /* Client-to-Server */
1537                                         message_type = "Type 55";
1538                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1539                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1540                                         offset += 4;
1541                                 }
1542                         break;
1543
1544                         case 56:
1545                                 if (check_slsk_format(tvb, offset, "i")) {
1546                                         /* Client-to-Server */
1547                                         message_type = "Get Global Rankings";
1548                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1549                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1550                                         offset += 4;
1551                                 }
1552                                 else if (check_slsk_format(tvb, offset, "ii*")) {
1553                                         /* Server-to-Client */
1554                                         message_type = "Get Global Rankings Reply";
1555                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1556                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1557                                         offset += 4;
1558                                         i=0; j = tvb_get_letohl(tvb, offset);
1559                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1560                                                 "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
1561                                         offset += 4;
1562                                         while (i<j){
1563                                                 if (check_slsk_format(tvb, offset, "si*")) {
1564                                                         guint32 len;
1565
1566                                                         len = tvb_get_letohl(tvb, offset);
1567                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
1568                                                                 "String #%d Length: %d", i+1, len);
1569                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
1570                                                                 "Recommendation #%d: %s", i+1,
1571                                                                 tvb_format_text(tvb, offset+4, len));
1572                                                         offset += 4+len;
1573                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_ranking, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1574                                                                 "Ranking #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1575                                                         offset += 4;
1576                                                 }
1577                                                 i++;
1578                                         }
1579                                 }
1580                         break;
1581
1582                         case 57:
1583                                 if (check_slsk_format(tvb, offset, "is")) {
1584                                         /* Client-to-Server */
1585                                         message_type = "Get User Recommendations";
1586                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1587                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1588                                         offset += 4;
1589                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1590                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1591                                         offset += 4+tvb_get_letohl(tvb, offset);
1592                                 }
1593                                 else if (check_slsk_format(tvb, offset, "isi*")) {
1594                                         /* Server-to-Client */
1595                                         message_type = "Get User Recommendations Reply";
1596                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1597                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1598                                         offset += 4;
1599                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1600                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1601                                         offset += 4+tvb_get_letohl(tvb, offset);
1602                                         i=0; j = tvb_get_letohl(tvb, offset);
1603                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1604                                                 "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
1605                                         offset += 4;
1606                                         while (i<j){
1607                                                 if (check_slsk_format(tvb, offset, "s*")) {
1608                                                         guint32 len;
1609
1610                                                         len = tvb_get_letohl(tvb, offset);
1611                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
1612                                                                 "String #%d Length: %d", i+1, len);
1613                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
1614                                                                 "Recommendation #%d: %s", i+1,
1615                                                                 tvb_format_text(tvb, offset+4, len));
1616                                                         offset += 4+len;
1617                                                 }
1618                                                 i++;
1619                                         }
1620                                 }
1621                         break;
1622
1623                         case 58:
1624                                 if (check_slsk_format(tvb, offset, "isi*")) {
1625                                         /* Client-to-Server */
1626                                         message_type = "Admin Command";
1627                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1628                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1629                                         offset += 4;
1630                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1631                                         proto_tree_add_item(slsk_tree, hf_slsk_string, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1632                                         offset += 4+tvb_get_letohl(tvb, offset);
1633                                         i=0; j = tvb_get_letohl(tvb, offset);
1634                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1635                                                 "Number of Strings: %d", tvb_get_letohl(tvb, offset));
1636                                         offset += 4;
1637                                         while (i<j){
1638                                                 if (check_slsk_format(tvb, offset, "s*")) {
1639                                                         guint32 len;
1640
1641                                                         len = tvb_get_letohl(tvb, offset);
1642                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
1643                                                                 "String #%d Length: %d", i+1, len);
1644                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
1645                                                                 "String #%d: %s", i+1,
1646                                                                 tvb_format_text(tvb, offset+4, len));
1647                                                         offset += 4+len;
1648                                                 }
1649                                                 i++;
1650                                         }
1651                                 }
1652                         break;
1653
1654                         case 60:
1655                                 if (check_slsk_format(tvb, offset, "isii")) {
1656                                         /* Client-to-Server & Server-to-Client */
1657                                         message_type = "Place In Line Response";
1658                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1659                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1660                                         offset += 4;
1661                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1662                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1663                                         offset += 4+tvb_get_letohl(tvb, offset);
1664                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1665                                         offset += 4;
1666                                         proto_tree_add_uint(slsk_tree, hf_slsk_place_in_queue, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1667                                         offset += 4;
1668                                 }
1669                         break;
1670
1671                         case 62:
1672                                 if (check_slsk_format(tvb, offset, "is")) {
1673                                         /* Server-to-Client */
1674                                         message_type = "Room Added";
1675                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1676                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1677                                         offset += 4;
1678                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1679                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1680                                         offset += 4+tvb_get_letohl(tvb, offset);
1681                                 }
1682                         break;
1683
1684                         case 63:
1685                                 if (check_slsk_format(tvb, offset, "is")) {
1686                                         /* Server-to-Client */
1687                                         message_type = "Room Removed";
1688                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1689                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1690                                         offset += 4;
1691                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1692                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1693                                         offset += 4+tvb_get_letohl(tvb, offset);
1694                                 }
1695                         break;
1696
1697                         case 64:
1698                                 if (check_slsk_format(tvb, offset, "i")) {
1699                                         /* Client-to-Server */
1700                                         message_type = "Room List Request";
1701                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1702                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1703                                         offset += 4;
1704                                 }
1705                                 else if (check_slsk_format(tvb, offset, "ii*")) {
1706                                         /* Server-to-Client */
1707                                         message_type = "Room List";
1708                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1709                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1710                                         offset += 4;
1711                                         i=0; j = tvb_get_letohl(tvb, offset);
1712                                         proto_tree_add_uint(slsk_tree, hf_slsk_number_of_rooms, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1713                                         offset += 4;
1714                                         while (i<j){
1715                                                 if (check_slsk_format(tvb, offset, "s*")) {
1716                                                         guint32 len;
1717
1718                                                         len = tvb_get_letohl(tvb, offset);
1719                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
1720                                                                 "String #%d Length: %d", i+1, len);
1721                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
1722                                                                 "Room #%d: %s", i+1,
1723                                                                 tvb_format_text(tvb, offset+4, len));
1724                                                         offset += 4+len;
1725                                                 }
1726                                                 i++;
1727                                         }
1728                                         if (check_slsk_format(tvb, offset, "i*")) {
1729                                                 i=0;
1730                                                 proto_tree_add_uint(slsk_tree, hf_slsk_number_of_rooms, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1731                                                 offset += 4;
1732                                                 while (i<j){
1733                                                         if (check_slsk_format(tvb, offset, "i*")) {
1734                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1735                                                                         "Users in Room #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1736                                                                 offset += 4;
1737                                                         }
1738                                                         i++;
1739                                                 }
1740                                         }
1741                                 }
1742                         break;
1743
1744                         case 65:
1745                                 if (check_slsk_format(tvb, offset, "isissiii")) {
1746                                         /* Server-to-Client */
1747                                         message_type = "Exact File Search";
1748                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1749                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1750                                         offset += 4;
1751                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1752                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1753                                         offset += 4+tvb_get_letohl(tvb, offset);
1754                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1755                                         offset += 4;
1756                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1757                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1758                                         offset += 4+tvb_get_letohl(tvb, offset);
1759                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1760                                         proto_tree_add_item(slsk_tree, hf_slsk_directory, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1761                                         offset += 4+tvb_get_letohl(tvb, offset);
1762                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 16, 0,
1763                                                 "(+12 0 bytes)");
1764                                         offset += 12;
1765                                 }
1766                                 else if (check_slsk_format(tvb, offset, "iissiiib")) {
1767                                         /* Client-to-Server */
1768                                         message_type = "Exact File Search";
1769                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1770                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1771                                         offset += 4;
1772                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1773                                         offset += 4;
1774                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1775                                         proto_tree_add_item(slsk_tree, hf_slsk_filename, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1776                                         offset += 4+tvb_get_letohl(tvb, offset);
1777                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1778                                         proto_tree_add_item(slsk_tree, hf_slsk_directory, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1779                                         offset += 4+tvb_get_letohl(tvb, offset);
1780                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 13, 0,
1781                                                 "(+13 0 bytes)");
1782                                         offset += 13;
1783                                 }
1784                         break;
1785
1786                         case 66:
1787                                 if (check_slsk_format(tvb, offset, "is")) {
1788                                         /* Server-to-Client */
1789                                         message_type = "Admin Message";
1790                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1791                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1792                                         offset += 4;
1793                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1794                                         proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1795                                         offset += 4+tvb_get_letohl(tvb, offset);
1796                                 }
1797                         break;
1798
1799                         case 67:
1800                                 if (check_slsk_format(tvb, offset, "i")) {
1801                                         /* Client-to-Server */
1802                                         message_type = "Global User List Request";
1803                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1804                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1805                                         offset += 4;
1806                                 }
1807                                 else if (check_slsk_format(tvb, offset, "isi*")) {              /* same as case 14 */
1808                                         /* Server-to-Client */
1809                                         message_type = "Global User List";
1810                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1811                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1812                                         offset += 4;
1813                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1814                                         proto_tree_add_item(slsk_tree, hf_slsk_room, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1815                                         offset += 4+tvb_get_letohl(tvb, offset);
1816                                         i=0; j = tvb_get_letohl(tvb, offset);
1817                                         proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1818                                         offset += 4;
1819                                         while (i<j){
1820                                                 if (check_slsk_format(tvb, offset, "s*")) {
1821                                                         guint32 len;
1822
1823                                                         len = tvb_get_letohl(tvb, offset);
1824                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
1825                                                                 "String #%d Length: %d", i+1, len);
1826                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
1827                                                                 "User #%d: %s", i+1,
1828                                                                 tvb_format_text(tvb, offset+4, len));
1829                                                         offset += 4+len;
1830                                                 }
1831                                                 i++;
1832                                         }
1833                                         if (check_slsk_format(tvb, offset, "i*")) {
1834                                                 i=0; j = tvb_get_letohl(tvb, offset);
1835                                                 proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, j);
1836                                                 offset += 4;
1837                                                 while (i<j){
1838                                                         if (check_slsk_format(tvb, offset, "i*")) {
1839                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_status_code, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1840                                                                         "Status of User #%d: %s (Code: %d)", i+1, val_to_str(tvb_get_letohl(tvb, offset), slsk_status_codes, "Unknown"), tvb_get_letohl(tvb, offset));
1841                                                                 offset += 4;
1842                                                         }
1843                                                         i++;
1844                                                 }
1845                                         }
1846                                         if (check_slsk_format(tvb, offset, "i*")) {
1847                                                 i=0; j = tvb_get_letohl(tvb, offset);
1848                                                 proto_tree_add_uint(slsk_tree, hf_slsk_users_in_room, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1849                                                 offset += 4;
1850                                                 while (i<j){
1851                                                         if (check_slsk_format(tvb, offset, "iiiii*")) {
1852                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1853                                                                         "Average Speed of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1854                                                                 offset += 4;
1855                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1856                                                                         "Downloadnum of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1857                                                                 offset += 4;
1858                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1859                                                                         "Something of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1860                                                                 offset += 4;
1861                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1862                                                                         "Files of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1863                                                                 offset += 4;
1864                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1865                                                                         "Folders of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1866                                                                 offset += 4;
1867                                                         }
1868                                                         i++;
1869                                                 }
1870                                         }
1871                                         if (check_slsk_format(tvb, offset, "i*")) {
1872                                                 i=0; j = tvb_get_letohl(tvb, offset);
1873                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1874                                                         "Number of Slotsfull Records: %d", tvb_get_letohl(tvb, offset));
1875                                                 offset += 4;
1876                                                 while (i<j){
1877                                                         if (check_slsk_format(tvb, offset, "i*")) {
1878                                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1879                                                                         "Slots full of User #%d: %d", i+1, tvb_get_letohl(tvb, offset));
1880                                                                 offset += 4;
1881                                                         }
1882                                                         i++;
1883                                                 }
1884                                         }
1885                                 }
1886                         break;
1887
1888                         case 68:
1889                                 if (check_slsk_format(tvb, offset, "isiiiis")) {
1890                                         message_type = "Tunneled Message";
1891                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1892                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1893                                         offset += 4;
1894                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1895                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1896                                         offset += 4+tvb_get_letohl(tvb, offset);
1897                                         proto_tree_add_uint(slsk_tree, hf_slsk_code, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1898                                         offset += 4;
1899                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1900                                         offset += 4;
1901                                         proto_tree_add_ipv4(slsk_tree, hf_slsk_ip, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
1902                                         offset += 4;
1903                                         proto_tree_add_uint(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1904                                         offset += 4;
1905                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1906                                         proto_tree_add_item(slsk_tree, hf_slsk_chat_message, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
1907                                         offset += 4+tvb_get_letohl(tvb, offset);
1908                                 }
1909                         break;
1910
1911                         case 69:
1912                                 if (check_slsk_format(tvb, offset, "i")) {
1913                                         /* Client-to-Server */
1914                                         message_type = "Privileged User List Request";
1915                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1916                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1917                                         offset += 4;
1918                                 }
1919                                 else if (check_slsk_format(tvb, offset, "ii*")) {
1920                                         /* Server-to-Client */
1921                                         message_type = "Privileged User List";
1922                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1923                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1924                                         offset += 4;
1925                                         i=0; j = tvb_get_letohl(tvb, offset);
1926                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, tvb_get_letohl(tvb, offset),
1927                                                 "Number of Privileged Users: %d", tvb_get_letohl(tvb, offset));
1928                                         offset += 4;
1929                                         while (i<j){
1930                                                 if (check_slsk_format(tvb, offset, "s*")) {
1931                                                         guint32 len;
1932
1933                                                         len = tvb_get_letohl(tvb, offset);
1934                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
1935                                                                 "String #%d Length: %d", i+1, len);
1936                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
1937                                                                 "User #%d: %s", i+1,
1938                                                                 tvb_format_text(tvb, offset+4, len));
1939                                                         offset += 4+len;
1940                                                 }
1941                                                 i++;
1942                                         }
1943                                 }
1944                         break;
1945
1946                         case 71:
1947                                 if (check_slsk_format(tvb, offset, "ib")) {
1948                                         /* Client-to-Server */
1949                                         message_type = "Get Parent List";
1950                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1951                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1952                                         offset += 4;
1953                                         proto_tree_add_uint(slsk_tree, hf_slsk_byte, tvb, offset, 1, tvb_get_guint8(tvb, offset));
1954                                         offset += 1;
1955                                 }
1956                         break;
1957
1958                         case 73:
1959                                 if (check_slsk_format(tvb, offset, "ii")) {
1960                                         /* Client-to-Server */
1961                                         message_type = "Type 73";
1962                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1963                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1964                                         offset += 4;
1965                                         proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1966                                         offset += 4;
1967                                 }
1968                         break;
1969
1970                         case 83:
1971                                 if (check_slsk_format(tvb, offset, "ii")) {
1972                                         /* Server-to-Client */
1973                                         message_type = "Parent Min Speed";
1974                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1975                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1976                                         offset += 4;
1977                                         proto_tree_add_uint(slsk_tree, hf_slsk_parent_min_speed, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1978                                         offset += 4;
1979                                 }
1980                         break;
1981
1982                         case 84:
1983                                 if (check_slsk_format(tvb, offset, "ii")) {
1984                                         /* Server-to-Client */
1985                                         message_type = "Parent Speed Connection Ratio";
1986                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1987                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
1988                                         offset += 4;
1989                                         proto_tree_add_uint(slsk_tree, hf_slsk_parent_speed_connection_ratio, tvb, offset, 4, tvb_get_letohl(tvb, offset));
1990                                         offset += 4;
1991                                 }
1992                         break;
1993
1994                         case 86:
1995                                 if (check_slsk_format(tvb, offset, "ii")) {
1996                                         /* Server-to-Client */
1997                                         message_type = "Parent Inactivity Before Disconnect";
1998                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
1999                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2000                                         offset += 4;
2001                                         proto_tree_add_uint(slsk_tree, hf_slsk_seconds_parent_inactivity_before_disconnect, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2002                                         offset += 4;
2003                                 }
2004                         break;
2005
2006                         case 87:
2007                                 if (check_slsk_format(tvb, offset, "ii")) {
2008                                         /* Server-to-Client */
2009                                         message_type = "Server Inactivity Before Disconnect";
2010                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2011                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2012                                         offset += 4;
2013                                         proto_tree_add_uint(slsk_tree, hf_slsk_seconds_server_inactivity_before_disconnect, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2014                                         offset += 4;
2015                                 }
2016                         break;
2017
2018                         case 88:
2019                                 if (check_slsk_format(tvb, offset, "ii")) {
2020                                         /* Server-to-Client */
2021                                         message_type = "Nodes In Cache Before Disconnect";
2022                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2023                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2024                                         offset += 4;
2025                                         proto_tree_add_uint(slsk_tree, hf_slsk_nodes_in_cache_before_disconnect, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2026                                         offset += 4;
2027                                 }
2028                         break;
2029
2030                         case 90:
2031                                 if (check_slsk_format(tvb, offset, "ii")) {
2032                                         /* Server-to-Client */
2033                                         message_type = "Seconds Before Ping Children";
2034                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2035                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2036                                         offset += 4;
2037                                         proto_tree_add_uint(slsk_tree, hf_slsk_seconds_before_ping_children, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2038                                         offset += 4;
2039                                 }
2040                         break;
2041
2042                         case 91:
2043                                 if (check_slsk_format(tvb, offset, "is")) {
2044                                         /* Server-to-Client */
2045                                         message_type = "Add To Privileged";
2046                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2047                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2048                                         offset += 4;
2049                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2050                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2051                                         offset += 4+tvb_get_letohl(tvb, offset);
2052                                 }
2053                         break;
2054
2055                         case 92:
2056                                 if (check_slsk_format(tvb, offset, "i")) {
2057                                         /* Client-to-Server */
2058                                         message_type = "Check Privileges";
2059                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2060                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2061                                         offset += 4;
2062                                 }
2063                                 else if (check_slsk_format(tvb, offset, "ii")) {
2064                                         /* Server-to-Client */
2065                                         message_type = "Check Privileges Reply";
2066                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2067                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2068                                         offset += 4;
2069                                         proto_tree_add_uint(slsk_tree, hf_slsk_number_of_days, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2070                                         offset += 4;
2071                                 }
2072                         break;
2073
2074                         case 93:
2075                                 if (check_slsk_format(tvb, offset, "ibisis")) {
2076                                         /* Server-to-Client */
2077                                         message_type = "Embedded Message";
2078                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2079                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2080                                         offset += 4;
2081                                         if ( tvb_get_guint8(tvb, offset) == 3 ){
2082                                                 /* Client-to-Client */
2083                                                 message_type = "Distributed Search";
2084                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
2085                                                                        "Embedded Message Type: %s (Byte: %d)", message_type, 3);
2086                                                 offset += 1;
2087                                                 proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2088                                                 offset += 4;
2089                                                 proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2090                                                 proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2091                                                 offset += 4+tvb_get_letohl(tvb, offset);
2092                                                 proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2093                                                 offset += 4;
2094                                                 proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2095                                                 proto_tree_add_item(slsk_tree, hf_slsk_search_text, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2096                                                 offset += 4+tvb_get_letohl(tvb, offset);
2097                                         }
2098                                 }
2099                         break;
2100
2101                         case 100:
2102                                 if (check_slsk_format(tvb, offset, "ib")) {
2103                                         /* Client-to-Server */
2104                                         message_type = "Become Parent";
2105                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2106                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2107                                         offset += 4;
2108                                         proto_tree_add_uint(slsk_tree, hf_slsk_byte, tvb, offset, 1, tvb_get_guint8(tvb, offset));
2109                                         offset += 1;
2110                                 }
2111                         break;
2112
2113                         case 102:
2114                                 if (check_slsk_format(tvb, offset, "ii*")) {
2115                                         /* Server-to-Client */
2116                                         message_type = "Random Parent Addresses";
2117                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2118                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2119                                         offset += 4;
2120                                         i=0; j = tvb_get_letohl(tvb, offset);
2121                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, tvb_get_letohl(tvb, offset),
2122                                                 "Number of Parent Addresses: %d", tvb_get_letohl(tvb, offset));
2123                                         offset += 4;
2124                                         while (i<j){
2125                                                 if (check_slsk_format(tvb, offset, "sii*")) {
2126                                                         guint32 len;
2127
2128                                                         len = tvb_get_letohl(tvb, offset);
2129                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
2130                                                                 "String #%d Length: %d", i+1, len);
2131                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
2132                                                                 "User #%d: %s", i+1,
2133                                                                 tvb_format_text(tvb, offset+4, len));
2134                                                         offset += 4+len;
2135                                                         proto_tree_add_item(slsk_tree, hf_slsk_ip, tvb, offset, 4, FALSE);
2136                                                         offset += 4;
2137                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_port, tvb, offset, 4, tvb_get_letohl(tvb, offset),
2138                                                                 "Port Number #%d: %d", i+1, tvb_get_letohl(tvb, offset));
2139                                                         offset += 4;
2140                                                 }
2141                                                 i++;
2142                                         }
2143                                 }
2144                         break;
2145
2146                         case 103:
2147                                 if (check_slsk_format(tvb, offset, "iis")) {
2148                                         /* Server-to-Client */
2149                                         message_type = "Send Wishlist Entry";
2150                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2151                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2152                                         offset += 4;
2153                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2154                                         offset += 4;
2155                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2156                                         proto_tree_add_item(slsk_tree, hf_slsk_search_text, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2157                                         offset += 4+tvb_get_letohl(tvb, offset);
2158                                 }
2159                         break;
2160
2161                         case 104:
2162                                 if (check_slsk_format(tvb, offset, "ii")) {
2163                                         /* Server-to-Client */
2164                                         message_type = "Type 104";
2165                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2166                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2167                                         offset += 4;
2168                                         proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2169                                         offset += 4;
2170                                 }
2171                         break;
2172
2173                         case 110:
2174                                 if (check_slsk_format(tvb, offset, "i")) {
2175                                         /* Client-to-Server */
2176                                         message_type = "Get Similar Users";
2177                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2178                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2179                                         offset += 4;
2180                                 }
2181                                 else if (check_slsk_format(tvb, offset, "ii*")) {
2182                                         /* Server-to-Client */
2183                                         message_type = "Get Similar Users Reply";
2184                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2185                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2186                                         offset += 4;
2187                                         i=0; j = tvb_get_letohl(tvb, offset);
2188                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_number_of_users, tvb, offset, 4, tvb_get_letohl(tvb, offset),
2189                                                 "Number of Users: %d", tvb_get_letohl(tvb, offset));
2190                                         offset += 4;
2191                                         while (i<j){
2192                                                 if (check_slsk_format(tvb, offset, "si*")) {
2193                                                         guint32 len;
2194
2195                                                         len = tvb_get_letohl(tvb, offset);
2196                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
2197                                                                 "String #%d Length: %d", i+1, len);
2198                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
2199                                                                 "User #%d: %s", i+1,
2200                                                                 tvb_format_text(tvb, offset+4, len));
2201                                                         offset += 4+len;
2202                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
2203                                                                 "Same Recommendations #%d: %d", i+1, tvb_get_letohl(tvb, offset));
2204                                                         offset += 4;
2205                                                 }
2206                                                 i++;
2207                                         }
2208                                 }
2209                         break;
2210
2211                         case 111:
2212                                 if (check_slsk_format(tvb, offset, "is")) {
2213                                         /* Client-to-Server */
2214                                         message_type = "Get Recommendations for Item";
2215                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2216                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2217                                         offset += 4;
2218                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2219                                         proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2220                                         offset += 4+tvb_get_letohl(tvb, offset);
2221                                 }
2222                                 else if (check_slsk_format(tvb, offset, "isi*")) {
2223                                         /* Server-to-Client */
2224                                         message_type = "Get Recommendations for Item Reply";
2225                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2226                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2227                                         offset += 4;
2228                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2229                                         proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2230                                         offset += 4+tvb_get_letohl(tvb, offset);
2231                                         i=0; j = tvb_get_letohl(tvb, offset);
2232                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
2233                                                 "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
2234                                         offset += 4;
2235                                         while (i<j){
2236                                                 if (check_slsk_format(tvb, offset, "si*")) {
2237                                                         guint32 len;
2238
2239                                                         len = tvb_get_letohl(tvb, offset);
2240                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
2241                                                                 "String #%d Length: %d", i+1, len);
2242                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
2243                                                                 "Recommendation #%d: %s", i+1,
2244                                                                 tvb_format_text(tvb, offset+4, len));
2245                                                         offset += 4+len;
2246                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_ranking, tvb, offset, 4, tvb_get_letohl(tvb, offset),
2247                                                                 "Ranking #%d: %d", i+1, tvb_get_letohl(tvb, offset));
2248                                                         offset += 4;
2249                                                 }
2250                                                 i++;
2251                                         }
2252                                 }
2253                         break;
2254
2255                         case 112:
2256                                 if (check_slsk_format(tvb, offset, "is")) {
2257                                         /* Client-to-Server */
2258                                         message_type = "Get Similar Users for Item";
2259                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2260                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2261                                         offset += 4;
2262                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2263                                         proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2264                                         offset += 4+tvb_get_letohl(tvb, offset);
2265                                 }
2266                                 else if (check_slsk_format(tvb, offset, "isi*")) {
2267                                         /* Server-to-Client */
2268                                         message_type = "Get Similar Users for Item Reply";
2269                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2270                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2271                                         offset += 4;
2272                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2273                                         proto_tree_add_item(slsk_tree, hf_slsk_recommendation, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2274                                         offset += 4+tvb_get_letohl(tvb, offset);
2275                                         i=0; j = tvb_get_letohl(tvb, offset);
2276                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset),
2277                                                 "Number of Recommendations: %d", tvb_get_letohl(tvb, offset));
2278                                         offset += 4;
2279                                         while (i<j){
2280                                                 if (check_slsk_format(tvb, offset, "s*")) {
2281                                                         guint32 len;
2282
2283                                                         len = tvb_get_letohl(tvb, offset);
2284                                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len,
2285                                                                 "String #%d Length: %d", i+1, len);
2286                                                         proto_tree_add_text(slsk_tree, tvb, offset+4, len,
2287                                                                 "Username #%d: %s", i+1,
2288                                                                 tvb_format_text(tvb, offset+4, len));
2289                                                         offset += 4+len;
2290                                                 }
2291                                                 i++;
2292                                         }
2293                                 }
2294                         break;
2295
2296                         case 1001:
2297                                 if (check_slsk_format(tvb, offset, "iis")) {
2298                                         /* Client-to-Server */
2299                                         message_type = "Can't Connect To Peer";
2300                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2301                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2302                                         offset += 4;
2303                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2304                                         offset += 4;
2305                                         proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2306                                         proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2307                                         offset += 4+tvb_get_letohl(tvb, offset);
2308                                 }
2309                                 else if (check_slsk_format(tvb, offset, "ii")) {
2310                                         /* Server-to-Client */
2311                                         message_type = "Can't Connect To Peer";
2312                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2313                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2314                                         offset += 4;
2315                                         proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2316                                         offset += 4;
2317                                 }
2318                         break;
2319
2320                         default:
2321                                 if (check_slsk_format(tvb, offset, "bisis")) {
2322                                         if ( tvb_get_guint8(tvb, offset) == 3 ){
2323                                                 /* Client-to-Client */
2324                                                 message_type = "Distributed Search";
2325                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
2326                                                                        "Message Type: %s (Byte: %d)", message_type, 3);
2327                                                 offset += 1;
2328                                                 proto_tree_add_uint(slsk_tree, hf_slsk_integer, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2329                                                 offset += 4;
2330                                                 proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2331                                                 proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2332                                                 offset += 4+tvb_get_letohl(tvb, offset);
2333                                                 proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2334                                                 offset += 4;
2335                                                 proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2336                                                 proto_tree_add_item(slsk_tree, hf_slsk_search_text, tvb, offset+4, tvb_get_letohl(tvb, offset), FALSE);
2337                                                 offset += 4+tvb_get_letohl(tvb, offset);
2338                                         }
2339                                 }
2340                                 else if (check_slsk_format(tvb, offset, "bssi")) {
2341                                         if ( tvb_get_guint8(tvb, offset) == 1 ){
2342                                                 /* Client-to-Client */
2343                                                 guint32 len;
2344
2345                                                 message_type = "Peer Init";
2346                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
2347                                                                        "Message Type: %s (Byte: %d)", message_type, 1);
2348                                                 offset += 1;
2349                                                 len = tvb_get_letohl(tvb, offset);
2350                                                 proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len);
2351                                                 proto_tree_add_item(slsk_tree, hf_slsk_username, tvb, offset+4, len, FALSE);
2352                                                 offset += 4+len;
2353                                                 len = tvb_get_letohl(tvb, offset);
2354                                                 proto_tree_add_uint(slsk_tree, hf_slsk_string_length, tvb, offset, 4, len);
2355                                                 str = tvb_get_ephemeral_string(tvb, offset+4, len);
2356                                                 proto_tree_add_string_format(slsk_tree, hf_slsk_connection_type, tvb, offset+4, len, str,
2357                                                         "Connection Type: %s (Char: %s)", connection_type(str),
2358                                                         format_text(str, len));
2359                                                 offset += 4+len;
2360                                                 proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2361                                                 offset += 4;
2362                                         }
2363                                 }
2364                                 else if (check_slsk_format(tvb, offset, "bi")) {
2365                                         if ( tvb_get_guint8(tvb, offset) == 0 ){
2366                                                 /* Client-to-Client */
2367                                                 message_type = "Pierce Fw";
2368                                                 proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 1, msg_code,
2369                                                                        "Message Type: %s (Byte: %d)", message_type, 0);
2370                                                 offset += 1;
2371                                                 proto_tree_add_uint(slsk_tree, hf_slsk_token, tvb, offset, 4, tvb_get_letohl(tvb, offset));
2372                                                 offset += 4;
2373                                         }
2374                                 }
2375                                 else {
2376                                         message_type = "Unknown";
2377                                         proto_tree_add_uint_format(slsk_tree, hf_slsk_message_code, tvb, offset, 4, msg_code,
2378                                                                "Message Type: %s (Code: %02d)", message_type, msg_code);
2379                                         offset += 4;
2380                                 }
2381                         break;
2382
2383                 }
2384
2385         }
2386
2387
2388 }
2389
2390
2391 static void dissect_slsk(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2392 {
2393         tcp_dissect_pdus(tvb, pinfo, tree, slsk_desegment, 4, get_slsk_pdu_len, dissect_slsk_pdu);
2394
2395 }
2396
2397
2398 /* Register the protocol with Wireshark */
2399
2400 void
2401 proto_register_slsk(void)
2402 {
2403
2404 /* Setup list of header fields  */
2405         static hf_register_info hf[] = {
2406                 { &hf_slsk_integer,
2407                         { "Integer", "slsk.integer",
2408                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2409                 { &hf_slsk_string,
2410                         { "String", "slsk.string",
2411                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2412                 { &hf_slsk_byte,
2413                         { "Byte", "slsk.byte",
2414                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2415                 { &hf_slsk_message_length,
2416                         { "Message Length", "slsk.message.length",
2417                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2418                 { &hf_slsk_message_code,
2419                         { "Message Code", "slsk.message.code",
2420                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2421                 { &hf_slsk_client_ip,
2422                         { "Client IP", "slsk.server.ip",
2423                         FT_IPv4, BASE_NONE, NULL, 0, "Client IP Address", HFILL } },
2424                 { &hf_slsk_server_ip,
2425                         { "SoulSeek Server IP", "slsk.server.ip",
2426                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2427                 { &hf_slsk_string_length,
2428                         { "String Length", "slsk.string.length",
2429                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2430                 { &hf_slsk_username,
2431                         { "Username", "slsk.username",
2432                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2433                 { &hf_slsk_password,
2434                         { "Password", "slsk.password",
2435                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2436                 { &hf_slsk_version,
2437                         { "Version", "slsk.version",
2438                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2439                 { &hf_slsk_login_successful,
2440                         { "Login successful", "slsk.login.successful",
2441                         FT_UINT8, BASE_DEC, NULL, 0, "Login Successful", HFILL } },
2442                 { &hf_slsk_login_message,
2443                         { "Login Message", "slsk.login.message",
2444                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2445                 { &hf_slsk_port,
2446                         { "Port Number", "slsk.port.number",
2447                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2448                 { &hf_slsk_ip,
2449                         { "IP Address", "slsk.ip.address",
2450                         FT_IPv4, BASE_NONE, NULL, 0, NULL, HFILL } },
2451                 { &hf_slsk_user_exists,
2452                         { "user exists", "slsk.user.exists",
2453                         FT_UINT8, BASE_DEC, NULL, 0, "User exists", HFILL } },
2454                 { &hf_slsk_status_code,
2455                         { "Status Code", "slsk.status.code",
2456                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2457                 { &hf_slsk_room,
2458                         { "Room", "slsk.room",
2459                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2460                 { &hf_slsk_chat_message,
2461                         { "Chat Message", "slsk.chat.message",
2462                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2463                 { &hf_slsk_users_in_room,
2464                         { "Users in Room", "slsk.room.users",
2465                         FT_UINT32, BASE_DEC, NULL, 0, "Number of Users in Room", HFILL } },
2466                 { &hf_slsk_token,
2467                         { "Token", "slsk.token",
2468                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2469                 { &hf_slsk_connection_type,
2470                         { "Connection Type", "slsk.connection.type",
2471                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2472                 { &hf_slsk_chat_message_id,
2473                         { "Chat Message ID", "slsk.chat.message.id",
2474                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2475                 { &hf_slsk_timestamp,
2476                         { "Timestamp", "slsk.timestamp",
2477                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2478                 { &hf_slsk_search_text,
2479                         { "Search Text", "slsk.search.text",
2480                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2481                 { &hf_slsk_folder_count,
2482                         { "Folder Count", "slsk.folder.count",
2483                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2484                 { &hf_slsk_file_count,
2485                         { "File Count", "slsk.file.count",
2486                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2487                 { &hf_slsk_average_speed,
2488                         { "Average Speed", "slsk.average.speed",
2489                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2490                 { &hf_slsk_download_number,
2491                         { "Download Number", "slsk.download.number",
2492                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2493                 { &hf_slsk_files,
2494                         { "Files", "slsk.files",
2495                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2496                 { &hf_slsk_directories,
2497                         { "Directories", "slsk.directories",
2498                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2499                 { &hf_slsk_slotsfull,
2500                         { "Slots full", "slsk.slots.full",
2501                         FT_UINT32, BASE_DEC, NULL, 0, "Upload Slots Full", HFILL } },
2502                 { &hf_slsk_place_in_queue,
2503                         { "Place in Queue", "slsk.queue.place",
2504                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2505                 { &hf_slsk_number_of_rooms,
2506                         { "Number of Rooms", "slsk.room.count",
2507                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2508                 { &hf_slsk_filename,
2509                         { "Filename", "slsk.filename",
2510                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2511                 { &hf_slsk_directory,
2512                         { "Directory", "slsk.directory",
2513                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2514                 { &hf_slsk_size,
2515                         { "Size", "slsk.size",
2516                         FT_UINT32, BASE_DEC, NULL, 0, "File Size", HFILL } },
2517                 { &hf_slsk_checksum,
2518                         { "Checksum", "slsk.checksum",
2519                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2520                 { &hf_slsk_code,
2521                         { "Code", "slsk.code",
2522                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2523                 { &hf_slsk_number_of_users,
2524                         { "Number of Users", "slsk.user.count",
2525                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2526                 { &hf_slsk_number_of_days,
2527                         { "Number of Days", "slsk.day.count",
2528                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2529                 { &hf_slsk_transfer_direction,
2530                         { "Transfer Direction", "slsk.transfer.direction",
2531                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2532                 { &hf_slsk_user_description,
2533                         { "User Description", "slsk.user.description",
2534                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2535                 { &hf_slsk_picture_exists,
2536                         { "Picture exists", "slsk.user.picture.exists",
2537                         FT_UINT8, BASE_DEC, NULL, 0, "User has a picture", HFILL } },
2538                 { &hf_slsk_picture,
2539                         { "Picture", "slsk.user.picture",
2540                         FT_STRING, BASE_NONE, NULL, 0, "User Picture", HFILL } },
2541                 { &hf_slsk_user_uploads,
2542                         { "User uploads", "slsk.uploads.user",
2543                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2544                 { &hf_slsk_total_uploads,
2545                         { "Total uploads allowed", "slsk.uploads.total",
2546                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2547                 { &hf_slsk_queued_uploads,
2548                         { "Queued uploads", "slsk.uploads.queued",
2549                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2550                 { &hf_slsk_slots_available,
2551                         { "Upload Slots available", "slsk.uploads.available",
2552                         FT_UINT8, BASE_DEC, NULL, 0, NULL, HFILL } },
2553                 { &hf_slsk_allowed,
2554                         { "Download allowed", "slsk.user.allowed",
2555                         FT_UINT8, BASE_DEC, NULL, 0, "allowed", HFILL } },
2556                 { &hf_slsk_compr_packet,
2557                         { "[zlib compressed packet]", "slsk.compr.packet",
2558                         FT_NONE, BASE_NONE, NULL, 0, "zlib compressed packet", HFILL } },
2559                 { &hf_slsk_parent_min_speed,
2560                         { "Parent Min Speed", "slsk.parent.min.speed",
2561                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2562                 { &hf_slsk_parent_speed_connection_ratio,
2563                         { "Parent Speed Connection Ratio", "slsk.parent.speed.connection.ratio",
2564                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2565                 { &hf_slsk_seconds_parent_inactivity_before_disconnect,
2566                         { "Seconds Parent Inactivity Before Disconnect", "slsk.seconds.parent.inactivity.before.disconnect",
2567                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2568                 { &hf_slsk_seconds_server_inactivity_before_disconnect,
2569                         { "Seconds Server Inactivity Before Disconnect", "slsk.seconds.server.inactivity.before.disconnect",
2570                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2571                 { &hf_slsk_nodes_in_cache_before_disconnect,
2572                         { "Nodes In Cache Before Disconnect", "slsk.nodes.in.cache.before.disconnect",
2573                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2574                 { &hf_slsk_seconds_before_ping_children,
2575                         { "Seconds Before Ping Children", "slsk.seconds.before.ping.children",
2576                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2577                 { &hf_slsk_recommendation,
2578                         { "Recommendation", "slsk.recommendation",
2579                         FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } },
2580                 { &hf_slsk_ranking,
2581                         { "Ranking", "slsk.ranking",
2582                         FT_UINT32, BASE_DEC, NULL, 0, NULL, HFILL } },
2583         };
2584
2585 /* Setup protocol subtree array */
2586         static gint *ett[] = {
2587                 &ett_slsk,
2588                 &ett_slsk_compr_packet,
2589         };
2590         module_t *slsk_module;
2591
2592 /* Registers the protocol name and description */
2593         proto_slsk = proto_register_protocol("SoulSeek Protocol", "SoulSeek", "slsk");
2594
2595 /* Required function calls to register the header fields and subtrees used */
2596         proto_register_field_array(proto_slsk, hf, array_length(hf));
2597         proto_register_subtree_array(ett, array_length(ett));
2598
2599         slsk_module = prefs_register_protocol(proto_slsk, NULL);
2600
2601 /* Registers the options in the menu preferences */
2602         prefs_register_bool_preference(slsk_module, "desegment",
2603             "Reassemble SoulSeek messages spanning multiple TCP segments",
2604             "Whether the SoulSeek dissector should reassemble messages spanning multiple TCP segments."
2605             " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
2606             &slsk_desegment);
2607 #ifdef HAVE_LIBZ
2608         prefs_register_bool_preference(slsk_module, "decompress",
2609             "Decompress zlib compressed packets inside SoulSeek messages",
2610             "Whether the SoulSeek dissector should decompress all zlib compressed packets inside messages",
2611             &slsk_decompress);
2612 #endif
2613
2614 }
2615
2616
2617 void
2618 proto_reg_handoff_slsk(void)
2619 {
2620         dissector_handle_t slsk_handle;
2621
2622         slsk_handle = create_dissector_handle(dissect_slsk, proto_slsk);
2623         dissector_add("tcp.port", TCP_PORT_SLSK_1, slsk_handle);
2624         dissector_add("tcp.port", TCP_PORT_SLSK_2, slsk_handle);
2625         dissector_add("tcp.port", TCP_PORT_SLSK_3, slsk_handle);
2626 }
2627