* which are handled as streams, and don't have lengths
* and IDs such as are required for reassemble.h
*
- * $Id$
- *
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.h"
#include <glib.h>
#include <epan/packet.h>
#include <epan/stream.h>
#include <epan/tvbuff.h>
-/* number of streams to allocate memory for at once */
-#define MEMCHUNK_STREAM_COUNT 20
-
-/* ditto pdus */
-#define MEMCHUNK_PDU_COUNT 100
-
-/* ditto fragments */
-#define MEMCHUNK_FRAGMENT_COUNT 100
-
typedef struct {
- fragment_data *fd_head; /* the reassembled data, NULL
- * until we add the last fragment */
- guint32 pdu_number; /* Number of this PDU within the stream */
+ fragment_head *fd_head; /* the reassembled data, NULL
+ * until we add the last fragment */
+ guint32 pdu_number; /* Number of this PDU within the stream */
/* id of this pdu (globally unique) */
guint32 id;
struct stream_pdu_fragment
{
- guint32 len; /* the length of this fragment */
+ guint32 len; /* the length of this fragment */
stream_pdu_t *pdu;
gboolean final_fragment;
};
that here */
gboolean is_circuit;
union {
- const struct circuit *circuit;
- const struct conversation *conv;
+ const struct circuit *circuit;
+ const struct conversation *conv;
} circ;
int p2p_dir;
} stream_key_t;
/* hash func */
-guint stream_hash_func(gconstpointer k)
+static guint stream_hash_func(gconstpointer k)
{
const stream_key_t *key = (const stream_key_t *)k;
/* is_circuit is redundant to the circuit/conversation pointer */
- return ((guint)key->circ.circuit) ^ key->p2p_dir;
+ return (GPOINTER_TO_UINT(key->circ.circuit)) ^ key->p2p_dir;
}
/* compare func */
-gboolean stream_compare_func(gconstpointer a,
- gconstpointer b)
+static gboolean stream_compare_func(gconstpointer a,
+ gconstpointer b)
{
const stream_key_t *key1 = (const stream_key_t *)a;
const stream_key_t *key2 = (const stream_key_t *)b;
if( key1 -> p2p_dir != key2 -> p2p_dir ||
- key1-> is_circuit != key2 -> is_circuit )
- return FALSE;
-
+ key1-> is_circuit != key2 -> is_circuit )
+ return FALSE;
+
if( key1 -> is_circuit )
- return (key1 -> circ.circuit == key2 -> circ.circuit );
+ return (key1 -> circ.circuit == key2 -> circ.circuit );
else
- return (key1 -> circ.conv == key2 -> circ.conv );
+ return (key1 -> circ.conv == key2 -> circ.conv );
}
-/* memory pools */
-static GMemChunk *stream_keys = NULL;
-static GMemChunk *streams = NULL;
-
-
/* the hash table */
static GHashTable *stream_hash;
-/* init/reset function, call from stream_init() */
-static void init_stream_hash( void ) {
+/* cleanup reset function, call from stream_cleanup() */
+static void cleanup_stream_hash( void ) {
if( stream_hash != NULL ) {
- g_hash_table_destroy( stream_hash );
- stream_hash = NULL;
- }
-
- if( stream_keys != NULL ) {
- g_mem_chunk_destroy( stream_keys );
- stream_keys = NULL;
- }
-
- if( streams != NULL ) {
- g_mem_chunk_destroy( streams );
- streams = NULL;
+ g_hash_table_destroy( stream_hash );
+ stream_hash = NULL;
}
+}
- streams = g_mem_chunk_create(stream_t,
- MEMCHUNK_STREAM_COUNT,
- G_ALLOC_ONLY);
-
- stream_keys = g_mem_chunk_create(stream_key_t,
- MEMCHUNK_STREAM_COUNT,
- G_ALLOC_ONLY);
-
+/* init function, call from stream_init() */
+static void init_stream_hash( void ) {
+ g_assert(stream_hash==NULL);
stream_hash = g_hash_table_new(stream_hash_func,
- stream_compare_func);
+ stream_compare_func);
}
-
/* lookup function, returns null if not found */
static stream_t *stream_hash_lookup_circ( const struct circuit *circuit, int p2p_dir )
{
static stream_t *new_stream( stream_key_t *key )
{
stream_t *val;
-
- val = g_mem_chunk_alloc(streams);
+
+ val = wmem_new(wmem_file_scope(), stream_t);
val -> key = key;
val -> pdu_counter = 0;
val -> current_pdu = NULL;
{
stream_key_t *key;
- key = g_mem_chunk_alloc(stream_keys);
+ key = wmem_new(wmem_file_scope(), stream_key_t);
key->is_circuit = TRUE;
key->circ.circuit = circuit;
key->p2p_dir = p2p_dir;
{
stream_key_t *key;
- key = g_mem_chunk_alloc(stream_keys);
+ key = wmem_new(wmem_file_scope(), stream_key_t);
key->is_circuit = FALSE;
key->circ.conv = conv;
key->p2p_dir = p2p_dir;
*
* PDU data
*/
-static GMemChunk *pdus = NULL;
/* pdu counter, for generating unique pdu ids */
static guint32 pdu_counter;
+static void stream_cleanup_pdu_data(void)
+{
+}
static void stream_init_pdu_data(void)
{
- if( pdus != NULL ) {
- g_mem_chunk_destroy( pdus );
- pdus = NULL;
- }
-
- pdus = g_mem_chunk_create(stream_pdu_t,
- MEMCHUNK_PDU_COUNT,
- G_ALLOC_ONLY);
pdu_counter = 0;
}
static stream_pdu_t *stream_new_pdu(stream_t *stream)
{
stream_pdu_t *pdu;
- pdu = g_mem_chunk_alloc(pdus);
+ pdu = wmem_new(wmem_file_scope(), stream_pdu_t);
pdu -> fd_head = NULL;
pdu -> pdu_number = stream -> pdu_counter++;
pdu -> id = pdu_counter++;
/* hash func */
-guint fragment_hash_func(gconstpointer k)
+static guint fragment_hash_func(gconstpointer k)
{
const fragment_key_t *key = (const fragment_key_t *)k;
- return ((guint)key->stream) + ((guint)key -> framenum) + ((guint)key->offset);
+ return (GPOINTER_TO_UINT(key->stream)) + ((guint)key -> framenum) + ((guint)key->offset);
}
/* compare func */
-gboolean fragment_compare_func(gconstpointer a,
- gconstpointer b)
+static gboolean fragment_compare_func(gconstpointer a,
+ gconstpointer b)
{
const fragment_key_t *key1 = (const fragment_key_t *)a;
const fragment_key_t *key2 = (const fragment_key_t *)b;
return (key1 -> stream == key2 -> stream &&
- key1 -> framenum == key2 -> framenum &&
- key1 -> offset == key2 -> offset );
+ key1 -> framenum == key2 -> framenum &&
+ key1 -> offset == key2 -> offset );
}
-
-/* memory pools */
-static GMemChunk *fragment_keys = NULL;
-static GMemChunk *fragment_vals = NULL;
/* the hash table */
static GHashTable *fragment_hash;
-/* init/reset function, call from stream_init() */
-static void init_fragment_hash( void ) {
+/* cleanup function, call from stream_cleanup() */
+static void cleanup_fragment_hash( void ) {
if( fragment_hash != NULL ) {
- g_hash_table_destroy( fragment_hash );
- fragment_hash = NULL;
+ g_hash_table_destroy( fragment_hash );
+ fragment_hash = NULL;
}
+}
- if( fragment_vals != NULL ) {
- g_mem_chunk_destroy( fragment_vals );
- fragment_vals = NULL;
- }
-
- if( fragment_keys != NULL ) {
- g_mem_chunk_destroy( fragment_keys );
- fragment_keys = NULL;
- }
-
- fragment_keys = g_mem_chunk_create(fragment_key_t,
- MEMCHUNK_FRAGMENT_COUNT,
- G_ALLOC_ONLY);
-
- fragment_vals = g_mem_chunk_create(stream_pdu_fragment_t,
- MEMCHUNK_FRAGMENT_COUNT,
- G_ALLOC_ONLY);
-
+/* init function, call from stream_init() */
+static void init_fragment_hash( void ) {
+ g_assert(fragment_hash==NULL);
fragment_hash = g_hash_table_new(fragment_hash_func,
- fragment_compare_func);
+ fragment_compare_func);
}
key.stream = stream;
key.framenum = framenum;
key.offset = offset;
- val = g_hash_table_lookup(fragment_hash, &key);
+ val = (stream_pdu_fragment_t *)g_hash_table_lookup(fragment_hash, &key);
return val;
}
/* insert function */
static stream_pdu_fragment_t *fragment_hash_insert( const stream_t *stream, guint32 framenum, guint32 offset,
- guint32 length)
+ guint32 length)
{
fragment_key_t *key;
stream_pdu_fragment_t *val;
- key = g_mem_chunk_alloc(fragment_keys);
+ key = wmem_new(wmem_file_scope(), fragment_key_t);
key->stream = stream;
key->framenum = framenum;
key->offset = offset;
- val = g_mem_chunk_alloc(fragment_vals);
+ val = wmem_new(wmem_file_scope(), stream_pdu_fragment_t);
val->len = length;
val->pdu = NULL;
val->final_fragment = FALSE;
/*****************************************************************************/
-/* fragmentation hash tables */
-static GHashTable *stream_fragment_table = NULL;
-static GHashTable *stream_reassembled_table = NULL;
+/* reassembly table */
+static reassembly_table stream_reassembly_table;
/* Initialise a new stream. Call this when you first identify a distinct
* stream. */
/* we don't want to replace the previous data if we get called twice on the
same circuit, so do a lookup first */
stream = stream_hash_lookup_circ(circuit, p2p_dir);
- g_assert( stream == NULL );
+ DISSECTOR_ASSERT( stream == NULL );
stream = stream_hash_insert_circ(circuit, p2p_dir);
-
+
return stream;
}
/* we don't want to replace the previous data if we get called twice on the
same conversation, so do a lookup first */
stream = stream_hash_lookup_conv(conv, p2p_dir);
- g_assert( stream == NULL );
+ DISSECTOR_ASSERT( stream == NULL );
stream = stream_hash_insert_conv(conv, p2p_dir);
return stream;
}
-
-
/* retrieve a previously-created stream.
*
* Returns null if no matching stream was found.
return stream_hash_lookup_conv(conv,p2p_dir);
}
+/* cleanup the stream routines */
+/* Note: stream_cleanup must only be called when seasonal memory
+ * is also freed since the hash tables countain pointers to
+ * wmem_file_scoped memory.
+ */
+void stream_cleanup( void )
+{
+ cleanup_stream_hash();
+ cleanup_fragment_hash();
+ stream_cleanup_pdu_data();
+ reassembly_table_destroy(&stream_reassembly_table);
+}
/* initialise the stream routines */
void stream_init( void )
init_fragment_hash();
stream_init_pdu_data();
- fragment_table_init(&stream_fragment_table);
- reassembled_table_init(&stream_reassembled_table);
+ reassembly_table_init(&stream_reassembly_table,
+ &addresses_reassembly_table_functions);
}
-
-
-
/*****************************************************************************/
stream_pdu_fragment_t *stream_find_frag( stream_t *stream, guint32 framenum, guint32 offset )
{
return fragment_hash_lookup( stream, framenum, offset );
}
-
+
stream_pdu_fragment_t *stream_add_frag( stream_t *stream, guint32 framenum, guint32 offset,
- tvbuff_t *tvb, packet_info *pinfo, gboolean more_frags )
+ tvbuff_t *tvb, packet_info *pinfo, gboolean more_frags )
{
- fragment_data *fd_head;
+ fragment_head *fd_head;
stream_pdu_t *pdu;
stream_pdu_fragment_t *frag_data;
- g_assert(stream);
+ DISSECTOR_ASSERT(stream);
/* check that this fragment is at the end of the stream */
- g_assert( framenum > stream->lastfrag_framenum ||
- (framenum == stream->lastfrag_framenum && offset > stream->lastfrag_offset));
+ DISSECTOR_ASSERT( framenum > stream->lastfrag_framenum ||
+ (framenum == stream->lastfrag_framenum && offset > stream->lastfrag_offset));
pdu = stream->current_pdu;
if( pdu == NULL ) {
- /* start a new pdu */
- pdu = stream->current_pdu = stream_new_pdu(stream);
+ /* start a new pdu */
+ pdu = stream->current_pdu = stream_new_pdu(stream);
}
-
+
/* add it to the reassembly tables */
- fd_head = fragment_add_seq_next(tvb, 0, pinfo, pdu->id,
- stream_fragment_table, stream_reassembled_table,
- tvb_reported_length(tvb), more_frags);
+ fd_head = fragment_add_seq_next(&stream_reassembly_table,
+ tvb, 0, pinfo, pdu->id, NULL,
+ tvb_reported_length(tvb), more_frags);
/* add it to our hash */
frag_data = fragment_hash_insert( stream, framenum, offset, tvb_reported_length(tvb));
frag_data -> pdu = pdu;
if( fd_head != NULL ) {
- /* if this was the last fragment, update the pdu data.
- */
- pdu -> fd_head = fd_head;
-
- /* start a new pdu next time */
- stream->current_pdu = NULL;
+ /* if this was the last fragment, update the pdu data.
+ */
+ pdu -> fd_head = fd_head;
+
+ /* start a new pdu next time */
+ stream->current_pdu = NULL;
frag_data -> final_fragment = TRUE;
}
tvbuff_t *stream_process_reassembled(
tvbuff_t *tvb, int offset, packet_info *pinfo,
- char *name, const stream_pdu_fragment_t *frag,
+ const char *name, const stream_pdu_fragment_t *frag,
const struct _fragment_items *fit,
gboolean *update_col_infop, proto_tree *tree)
{
stream_pdu_t *pdu;
- g_assert(frag);
+ DISSECTOR_ASSERT(frag);
pdu = frag->pdu;
/* we handle non-terminal fragments ourselves, because
return process_reassembled_data(tvb, offset, pinfo, name, pdu->fd_head,
fit, update_col_infop, tree);
}
-
+
guint32 stream_get_frag_length( const stream_pdu_fragment_t *frag)
{
- g_assert( frag );
+ DISSECTOR_ASSERT( frag );
return frag->len;
}
-fragment_data *stream_get_frag_data( const stream_pdu_fragment_t *frag)
+fragment_head *stream_get_frag_data( const stream_pdu_fragment_t *frag)
{
- g_assert( frag );
+ DISSECTOR_ASSERT( frag );
return frag->pdu->fd_head;
}
guint32 stream_get_pdu_no( const stream_pdu_fragment_t *frag)
{
- g_assert( frag );
+ DISSECTOR_ASSERT( frag );
return frag->pdu->pdu_number;
}
+
+/*
+ * Editor modelines - http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */