#include "pseudotcp.h"
#include "agent-enum-types.h"
-/* Maximum size of a UDP packet’s payload, as the packet’s length field is 16b
- * wide. */
-#define MAX_BUFFER_SIZE ((1 << 16) - 1) /* 65535 */
-
#define DEFAULT_STUN_PORT 3478
#define DEFAULT_UPNP_TIMEOUT 200 /* milliseconds */
#define DEFAULT_IDLE_TIMEOUT 5000 /* milliseconds */
* no data loss of packets already received and dequeued. */
if (has_io_callback) {
do {
- guint8 buf[MAX_BUFFER_SIZE];
gssize len;
/* FIXME: Why copy into a temporary buffer here? Why can’t the I/O
* callbacks be emitted directly from the pseudo-TCP receive buffer? */
- len = pseudo_tcp_socket_recv (sock, (gchar *) buf, sizeof(buf));
+ len = pseudo_tcp_socket_recv (sock, (gchar *) component->recv_buffer,
+ component->recv_buffer_size);
nice_debug ("%s: I/O callback case: Received %" G_GSSIZE_FORMAT " bytes",
G_STRFUNC, len);
break;
}
- nice_component_emit_io_callback (agent, component, buf, len);
+ nice_component_emit_io_callback (agent, component, len);
if (!agent_find_component (agent, stream_id, component_id,
&stream, &component)) {
* In fact, in the case of a reliable agent with I/O callbacks, zero
* memcpy()s can be achieved (for in-order packet delivery) by emittin the
* I/O callback directly from the pseudo-TCP receive buffer. */
- guint8 local_body_buf[MAX_BUFFER_SIZE];
GInputVector local_bufs[] = {
{ local_header_buf, sizeof (local_header_buf) },
- { local_body_buf, sizeof (local_body_buf) },
+ { component->recv_buffer, component->recv_buffer_size },
};
NiceInputMessage local_message = {
local_bufs, G_N_ELEMENTS (local_bufs), NULL, 0
}
} else if (has_io_callback) {
while (has_io_callback) {
- guint8 local_buf[MAX_BUFFER_SIZE];
- GInputVector local_bufs = { local_buf, sizeof (local_buf) };
+ GInputVector local_bufs = {
+ component->recv_buffer, component->recv_buffer_size
+ };
NiceInputMessage local_message = { &local_bufs, 1, NULL, 0 };
RecvStatus retval;
" bytes", G_STRFUNC, agent, local_message.length);
if (local_message.length > 0) {
- nice_component_emit_io_callback (agent, component, local_buf,
+ nice_component_emit_io_callback (agent, component,
local_message.length);
}
}
g_free ((gpointer) vec->buffer);
g_slice_free (GOutputVector, vec);
}
+
+ g_free (cmp->recv_buffer);
}
/*
/* This must be called with the agent lock *held*. */
void
nice_component_emit_io_callback (NiceAgent *agent, NiceComponent *component,
- const guint8 *buf, gsize buf_len)
+ gsize buf_len)
{
guint stream_id, component_id;
NiceAgentRecvFunc io_callback;
gpointer io_user_data;
g_assert (component != NULL);
- g_assert (buf != NULL);
g_assert (buf_len > 0);
stream_id = component->stream_id;
/* Thread owns the main context, so invoke the callback directly. */
agent_unlock_and_emit (agent);
io_callback (agent, stream_id,
- component_id, buf_len, (gchar *) buf, io_user_data);
+ component_id, buf_len, (gchar *) component->recv_buffer, io_user_data);
agent_lock (agent);
} else {
IOCallbackData *data;
/* Slow path: Current thread doesn’t own the Component’s context at the
* moment, so schedule the callback in an idle handler. */
- data = io_callback_data_new (buf, buf_len);
+ data = io_callback_data_new (component->recv_buffer, buf_len);
g_queue_push_tail (&component->pending_io_messages,
data); /* transfer ownership */
g_queue_init (&component->incoming_checks);
component->have_local_consent = TRUE;
+
+/* Maximum size of a UDP packet’s payload, as the packet’s length field is 16b
+ * wide. */
+#define MAX_BUFFER_SIZE ((1 << 16) - 1) /* 65535 */
+
+ component->recv_buffer = g_malloc (MAX_BUFFER_SIZE);
+ component->recv_buffer_size = MAX_BUFFER_SIZE;
}
static void
GQueue queued_tcp_packets;
gboolean have_local_consent;
+
+ /* scratch buffer for use in the component_io_cb() function to
+ * hold the incoming packet, allocated at component creation, since
+ * the callback is a critical path, where memory allocation should
+ * be avoided.
+ */
+ guint8 *recv_buffer;
+ guint recv_buffer_size;
};
typedef struct {
GError **error);
void
nice_component_emit_io_callback (NiceAgent *agent, NiceComponent *component,
- const guint8 *buf, gsize buf_len);
+ gsize buf_len);
gboolean
nice_component_has_io_callback (NiceComponent *component);
void