/** delay before firing roam events (ms) */
#define ROAM_DELAY 100
+#define ROAM_DELAY_RECHECK 1000
typedef struct private_android_net_t private_android_net_t;
* Socket used to determine source address
*/
int socket_v4;
+
+ /**
+ * Whether the device is currently connected
+ */
+ bool connected;
};
/**
time_monotonic(&now);
this->mutex->lock(this->mutex);
+ this->connected = !disconnected;
if (!timercmp(&now, &this->next_roam, >))
{
this->mutex->unlock(this->mutex);
struct sockaddr_in6 sin6;
} addr;
socklen_t addrlen;
+ timeval_t now;
+ job_t *job;
addrlen = *dest->get_sockaddr_len(dest);
addr.sockaddr.sa_family = AF_UNSPEC;
{
DBG1(DBG_KNL, "failed to connect socket: %s", strerror(errno));
}
+ else
+ {
+ time_monotonic(&now);
+ this->mutex->lock(this->mutex);
+ if (this->connected && timercmp(&now, &this->next_roam, >))
+ { /* we were not able to find a source address but reportedly are
+ * connected, trigger a recheck in case an IP address appears
+ * delayed but the callback is not triggered again */
+ timeval_add_ms(&now, ROAM_DELAY_RECHECK);
+ this->next_roam = now;
+ this->mutex->unlock(this->mutex);
+ job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
+ NULL, NULL, NULL);
+ lib->scheduler->schedule_job_ms(lib->scheduler, job,
+ ROAM_DELAY_RECHECK);
+ }
+ else
+ {
+ this->mutex->unlock(this->mutex);
+ }
+ }
return NULL;
}
if (getsockname(this->socket_v4, &addr.sockaddr, &addrlen) < 0)
}
charonservice->bypass_socket(charonservice, this->socket_v4, AF_INET);
- this->network_manager->add_connectivity_cb(this->network_manager,
- (void*)connectivity_cb, this);
+ this->mutex->lock(this->mutex);
+ this->network_manager->add_connectivity_cb(
+ this->network_manager, (void*)connectivity_cb, this);
+ this->connected = this->network_manager->is_connected(this->network_manager);
+ this->mutex->unlock(this->mutex);
return &this->public;
}