+ struct StunExternalIP *se;
+
+ /* Check if we had a prior response from this STUN server */
+ for (se = se_head; NULL != se; se = se->next)
+ {
+ if ( (se->stun_server_addr_len != sa_len) ||
+ (0 != memcmp (sa,
+ &se->stun_server_addr,
+ sa_len)) )
+ continue; /* different STUN server */
+ if (0 != memcmp (&external_addr,
+ &se->external_addr,
+ sizeof (struct sockaddr_in)))
+ {
+ /* external IP changed, update! */
+ notify_clients_stun_change (&se->external_addr,
+ GNUNET_NO);
+ se->external_addr = external_addr;
+ notify_clients_stun_change (&se->external_addr,
+ GNUNET_YES);
+ }
+ /* update timeout */
+ GNUNET_SCHEDULER_cancel (se->timeout_task);
+ se->timeout_task
+ = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
+ &stun_ip_timeout,
+ se);
+ return;
+ }
+ /* STUN server is completely new, create fresh entry */
+ se = GNUNET_new (struct StunExternalIP);
+ se->external_addr = external_addr;
+ GNUNET_memcpy (&se->stun_server_addr,
+ sa,
+ sa_len);
+ se->stun_server_addr_len = sa_len;
+ se->timeout_task = GNUNET_SCHEDULER_add_delayed (stun_stale_timeout,
+ &stun_ip_timeout,
+ se);
+ GNUNET_CONTAINER_DLL_insert (se_head,
+ se_tail,
+ se);
+ notify_clients_stun_change (&se->external_addr,
+ GNUNET_NO);