+ /* If this is UDP stream, allocate UDP remote stream hash table */
+ if (!engine->udp_remote && silc_socket_stream_is_udp(stream, NULL))
+ engine->udp_remote = silc_hash_table_alloc(0, silc_hash_string, NULL,
+ silc_hash_string_compare, NULL,
+ silc_packet_engine_hash_destr,
+ NULL, TRUE);
+
+ return ps;
+}
+
+/* Add new remote packet stream for UDP packet streams */
+
+SilcPacketStream silc_packet_stream_add_remote(SilcPacketStream stream,
+ const char *remote_ip,
+ SilcUInt16 remote_port)
+{
+ SilcPacketEngine engine = stream->engine;
+ SilcPacketStream ps;
+ char *tuple;
+ void *tmp;
+
+ SILC_LOG_DEBUG(("Adding UDP remote %s:%d to packet stream %p",
+ remote_ip, remote_port, stream));
+
+ if (!stream || !remote_ip || !remote_port)
+ return NULL;
+
+ if (!silc_socket_stream_is_udp(stream->stream, NULL)) {
+ SILC_LOG_ERROR(("Stream is not UDP stream, cannot add remote IP"));
+ return NULL;
+ }
+
+ ps = silc_calloc(1, sizeof(*ps));
+ if (!ps)
+ return NULL;
+
+ ps->engine = engine;
+ silc_atomic_init8(&ps->refcnt, 1);
+ silc_mutex_alloc(&ps->lock);
+
+ /* Set the UDP packet stream as underlaying stream */
+ silc_packet_stream_ref(stream);
+ ps->stream = (SilcStream)stream;
+ ps->udp = TRUE;
+
+ /* Allocate buffers */
+ tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
+ if (!tmp) {
+ silc_packet_stream_destroy(ps);
+ return NULL;
+ }
+ silc_buffer_set(&ps->inbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
+ silc_buffer_reset(&ps->inbuf);
+ tmp = silc_malloc(SILC_PACKET_DEFAULT_SIZE);
+ if (!tmp) {
+ silc_packet_stream_destroy(ps);
+ return NULL;
+ }
+ silc_buffer_set(&ps->outbuf, tmp, SILC_PACKET_DEFAULT_SIZE);
+ silc_buffer_reset(&ps->outbuf);
+
+ /* Initialize packet procesors list */
+ ps->process = silc_dlist_init();
+ if (!ps->process) {
+ silc_packet_stream_destroy(ps);
+ return NULL;
+ }
+
+ /* Add to engine with this IP and port pair */
+ tuple = silc_format("%d%s", remote_port, remote_ip);
+ silc_mutex_lock(engine->lock);
+ if (!tuple || !silc_hash_table_add(engine->udp_remote, tuple, ps)) {
+ silc_mutex_unlock(engine->lock);
+ silc_packet_stream_destroy(ps);
+ return NULL;
+ }
+ silc_mutex_unlock(engine->lock);
+
+ /* Save remote IP and port pair */
+ ps->remote_udp = silc_calloc(1, sizeof(*ps->remote_udp));
+ if (!ps->remote_udp) {
+ silc_packet_stream_destroy(ps);
+ return NULL;
+ }
+ ps->remote_udp->remote_port = remote_port;
+ ps->remote_udp->remote_ip = strdup(remote_ip);
+ if (!ps->remote_udp->remote_ip) {
+ silc_packet_stream_destroy(ps);
+ return NULL;
+ }
+