(s)->stream_context); \
} while(0)
+static void silc_packet_dispatch(SilcPacket packet);
+static void silc_packet_read_process(SilcPacketStream stream);
/************************ Static utility functions **************************/
-static void silc_packet_read_process(SilcPacketStream stream);
+/* Injects packet to new stream created with silc_packet_stream_add_remote. */
+
+SILC_TASK_CALLBACK(silc_packet_stream_inject_packet)
+{
+ SilcPacket packet = context;
+ SilcPacketStream stream = packet->stream;
+
+ SILC_LOG_DEBUG(("Injecting packet %p to stream %p", packet, packet->stream));
+
+ silc_mutex_lock(stream->lock);
+ silc_packet_dispatch(packet);
+ silc_mutex_unlock(stream->lock);
+}
/* Write data to the stream. Must be called with ps->lock locked. Unlocks
the lock inside this function. */
}
/* Save sender IP and port */
+ silc_free(ps->remote_udp->remote_ip);
ps->remote_udp->remote_ip = strdup(remote_ip);
ps->remote_udp->remote_port = remote_port;
SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
const char *remote_ip,
- SilcUInt16 remote_port)
+ SilcUInt16 remote_port,
+ SilcPacket packet)
{
SilcPacketEngine engine = stream->engine;
SilcPacketStream ps;
return NULL;
}
+ if (packet) {
+ /* Inject packet to the new stream */
+ packet->stream = ps;
+ silc_schedule_task_add_timeout(silc_stream_get_schedule(stream->stream),
+ silc_packet_stream_inject_packet, packet,
+ 0, 0);
+ }
+
return ps;
}
/* Return packet sender IP and port for UDP packet stream */
-SilcBool silc_packet_stream_get_sender(SilcPacketStream stream,
- const char **sender_ip,
- SilcUInt16 *sender_port)
+SilcBool silc_packet_get_sender(SilcPacket packet,
+ const char **sender_ip,
+ SilcUInt16 *sender_port)
{
- if (!stream->remote_udp)
+ if (!packet->stream->remote_udp)
return FALSE;
- *sender_ip = stream->remote_udp->remote_ip;
- *sender_port = stream->remote_udp->remote_port;
+ *sender_ip = packet->stream->remote_udp->remote_ip;
+ *sender_port = packet->stream->remote_udp->remote_port;
return TRUE;
}
/* Checks MAC in the packet. Returns TRUE if MAC is Ok. */
-static SilcBool silc_packet_check_mac(SilcHmac hmac,
- const unsigned char *data,
- SilcUInt32 data_len,
- const unsigned char *packet_mac,
- const unsigned char *packet_seq,
- SilcUInt32 sequence)
+static inline SilcBool silc_packet_check_mac(SilcHmac hmac,
+ const unsigned char *data,
+ SilcUInt32 data_len,
+ const unsigned char *packet_mac,
+ const unsigned char *packet_seq,
+ SilcUInt32 sequence)
{
/* Check MAC */
if (hmac) {
/* Decrypts SILC packet. Handles both normal and special packet decryption.
Return 0 when packet is normal and 1 when it it special, -1 on error. */
-static int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
- SilcUInt32 sequence, SilcBuffer buffer,
- SilcBool normal)
+static inline int silc_packet_decrypt(SilcCipher cipher, SilcHmac hmac,
+ SilcUInt32 sequence, SilcBuffer buffer,
+ SilcBool normal)
{
if (normal == TRUE) {
if (cipher) {
parsed. The buffer sent must be already decrypted before calling this
function. */
-static SilcBool silc_packet_parse(SilcPacket packet)
+static inline SilcBool silc_packet_parse(SilcPacket packet)
{
SilcBuffer buffer = &packet->buffer;
SilcUInt8 padlen = (SilcUInt8)buffer->data[4];
SILC_STR_UI_CHAR(&src_id_type),
SILC_STR_END);
if (ret == -1) {
- SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
+ if (!packet->stream->udp &&
+ !silc_socket_stream_is_udp(packet->stream->stream, NULL))
+ SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
return FALSE;
}
if (src_id_len > SILC_PACKET_MAX_ID_LEN ||
dst_id_len > SILC_PACKET_MAX_ID_LEN) {
- SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
- packet->src_id_len, packet->dst_id_len));
+ if (!packet->stream->udp &&
+ !silc_socket_stream_is_udp(packet->stream->stream, NULL))
+ SILC_LOG_ERROR(("Bad ID lengths in packet (%d and %d)",
+ packet->src_id_len, packet->dst_id_len));
return FALSE;
}
SILC_STR_OFFSET(padlen),
SILC_STR_END);
if (ret == -1) {
- SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
+ if (!packet->stream->udp &&
+ !silc_socket_stream_is_udp(packet->stream->stream, NULL))
+ SILC_LOG_ERROR(("Malformed packet header, packet dropped"));
return FALSE;
}
if (src_id_type > SILC_ID_CHANNEL ||
dst_id_type > SILC_ID_CHANNEL) {
- SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
- src_id_type, dst_id_type));
+ if (!packet->stream->udp &&
+ !silc_socket_stream_is_udp(packet->stream->stream, NULL))
+ SILC_LOG_ERROR(("Bad ID types in packet (%d and %d)",
+ src_id_type, dst_id_type));
return FALSE;
}
SilcBool default_sent = FALSE;
SilcPacketType *pt;
- /* Parse the packet */
- if (!silc_packet_parse(packet)) {
- silc_mutex_unlock(stream->lock);
- SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
- silc_mutex_lock(stream->lock);
- silc_packet_free(packet);
- return;
- }
-
/* Dispatch packet to all packet processors that want it */
if (!stream->process) {
/* Sanity checks */
if (packetlen < SILC_PACKET_MIN_LEN) {
- SILC_LOG_ERROR(("Received too short packet"));
+ if (!stream->udp && !silc_socket_stream_is_udp(stream->stream, NULL))
+ SILC_LOG_ERROR(("Received too short packet"));
silc_mutex_unlock(stream->lock);
SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
silc_mutex_lock(stream->lock);
/* Pull the packet from inbuf thus we'll get the next one in the inbuf. */
silc_buffer_pull(&stream->inbuf, paddedlen + mac_len);
+ /* Parse the packet */
+ if (!silc_packet_parse(packet)) {
+ silc_mutex_unlock(stream->lock);
+ SILC_PACKET_CALLBACK_ERROR(stream, SILC_PACKET_ERR_MALFORMED);
+ silc_mutex_lock(stream->lock);
+ silc_packet_free(packet);
+ memset(tmp, 0, sizeof(tmp));
+ return;
+ }
+
/* Dispatch the packet to application */
silc_packet_dispatch(packet);
}
SilcSchedule schedule,
SilcStream stream);
-/****f* silccore/SilcPacketAPI/silc_packet_stream_shared_create
+/****f* silccore/SilcPacketAPI/silc_packet_stream_add_remote
*
* SYNOPSIS
*
* SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
* const char *remote_ip,
- * SilcUInt16 remote_port);
+ * SilcUInt16 remote_port,
+ * SilcPacket packet);
*
* DESCRIPTION
*
* and port that does not have its own remote packet stream, it returns
* the packet to the packet callback set for `stream'. The sender's
* IP address and port can then be retrieved by using the
- * silc_packet_stream_get_sender function and to create new packet
- * stream by calling this function. After that, all packets from that
- * IP address and port will be received by the new packet stream.
+ * silc_packet_get_sender function and to create new packet stream by
+ * calling this function. After that, all packets from that IP address
+ * and port will be received by the new packet stream.
+ *
+ * If the `packet' is non-NULL it will be injected into the new packet
+ * stream as soon as the scheduler associated with `stream' schedules
+ * new tasks. It can be used to inject an incoming packet to the stream.
*
* This interface is for connectionless UDP streams. If it is possible
* to create connected stream it should be done for performance reasons.
*
* ...
* // Received a packet to the parent stream, get the sender information.
- * silc_packet_stream_get_sender(parent, &ip, &port);
+ * silc_packet_get_sender(packet, &ip, &port);
*
* // Create new packet stream for this remote location.
- * remote = silc_packet_stream_set_remote(parent, ip, port);
+ * remote = silc_packet_stream_add_remote(parent, ip, port, packet);
*
***/
SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
const char *remote_ip,
- SilcUInt16 remote_port);
+ SilcUInt16 remote_port,
+ SilcPacket packet);
/****f* silccore/SilcPacketAPI/silc_packet_stream_destroy
*
SilcPacketCallbacks *callbacks,
void *callback_context);
-/****f* silccore/SilcPacketAPI/silc_packet_stream_get_sender
+/****f* silccore/SilcPacketAPI/silc_packet_get_sender
*
* SYNOPSIS
*
- * SilcBool silc_packet_stream_get_sender(SilcPacketStream stream,
- * const char **sender_ip,
- * SilcUInt16 *sender_port);
+ * SilcBool silc_packet_get_sender(SilcPacket packet,
+ * const char **sender_ip,
+ * SilcUInt16 *sender_port);
*
* DESCRIPTION
*
- * Returns the packet sender's IP address and port from UDP packet stream
- * indicated by `stream'. This can be called only from the packet
+ * Returns the packet sender's IP address and port from UDP packet
+ * indicated by `packet'. This can be called only from the packet
* callback to retrieve the information of the packet's sender. Returns
* FALSE if the information is not available.
*
***/
-SilcBool silc_packet_stream_get_sender(SilcPacketStream stream,
- const char **sender_ip,
- SilcUInt16 *sender_port);
+SilcBool silc_packet_get_sender(SilcPacket packet,
+ const char **sender_ip,
+ SilcUInt16 *sender_port);
/****f* silccore/SilcPacketAPI/silc_packet_stream_ref
*