Fix some connections not shown

Some quick purged connections (e.g. DNS) were not shown. A 10 seconds
timeout is now used to ensure that all the connections are visualized.
This commit is contained in:
emanuele-f 2019-11-10 14:02:10 +01:00
parent fed5223a04
commit 31d4ea1af4
4 changed files with 86 additions and 10 deletions

View File

@ -19,6 +19,7 @@ import java.util.Objects;
public class ConnectionsAdapter extends BaseAdapter {
private static final String TAG = "ConnectionsAdapter";
private static final int MIN_CONNECTION_DISPLAY_SECONDS = 10;
private MainActivity mActivity;
private ArrayList<ConnDescriptor> mItems;
private Drawable mUnknownIcon;
@ -83,6 +84,8 @@ public class ConnectionsAdapter extends BaseAdapter {
}
void updateConnections(ConnDescriptor[] connections) {
long now = Utils.now();
/* Sort connections by ascending ID */
Arrays.sort(connections, new Comparator<ConnDescriptor>() {
@Override
@ -91,17 +94,17 @@ public class ConnectionsAdapter extends BaseAdapter {
}
});
/* NOTE: we could just replace all the connections objects instead of the merge code
* below. However, the code below might be useful in the future to implement more complex
* status change/cleanup. */
int adapter_pos = 0;
for (ConnDescriptor eval_conn : connections) {
ConnDescriptor adapter_conn = getItem(adapter_pos);
/* Remove the closed connections */
/* Check the closed connections */
while ((adapter_conn != null) && (eval_conn.incr_id > adapter_conn.incr_id)) {
mItems.remove(adapter_pos);
if((now - adapter_conn.first_seen) >= MIN_CONNECTION_DISPLAY_SECONDS)
mItems.remove(adapter_pos);
else
adapter_pos++;
adapter_conn = getItem(adapter_pos);
}

View File

@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable;
import android.util.Log;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class Utils {
@ -49,4 +50,9 @@ public class Utils {
}
return apps;
}
public static long now() {
Calendar calendar = Calendar.getInstance();
return(calendar.getTimeInMillis() / 1000);
}
}

View File

@ -63,6 +63,7 @@ typedef struct conn_data {
u_int32_t rcvd_pkts;
char *info;
int uid;
bool notified;
} conn_data_t;
/* ******************************************************* */
@ -439,6 +440,20 @@ static int handle_new_connection(zdtun_t *tun, const zdtun_conn_t *conn_info, vo
/* ******************************************************* */
static void free_connection_data(conn_data_t *data) {
if(!data)
return;
free_ndpi(data);
if(data->info)
free(data->info);
free(data);
}
/* ******************************************************* */
static void destroy_connection(zdtun_t *tun, const zdtun_conn_t *conn_info) {
conn_data_t *data = (conn_data_t*) conn_info->user_data;
@ -447,12 +462,35 @@ static void destroy_connection(zdtun_t *tun, const zdtun_conn_t *conn_info) {
return;
}
free_ndpi(data);
if(!data->notified) {
/* Connection was not notified to java. Copy it to a special list of pending connections */
vpnproxy_data_t *proxy = ((vpnproxy_data_t*)zdtun_userdata(tun));
if(data->info)
free(data->info);
if(proxy->cur_notif_pending >= proxy->notif_pending_size) {
/* Extend array */
if(proxy->notif_pending_size == 0)
proxy->notif_pending_size = 8;
else
proxy->notif_pending_size *= 2;
free(data);
proxy->notif_pending = realloc(proxy->notif_pending, proxy->notif_pending_size * sizeof(zdtun_conn_t));
if(proxy->notif_pending == NULL) {
__android_log_print(ANDROID_LOG_FATAL, VPN_TAG, "realloc(notif_pending) failed");
return;
}
}
memcpy(&proxy->notif_pending[proxy->cur_notif_pending], conn_info, sizeof(zdtun_conn_t));
proxy->cur_notif_pending++;
__android_log_print(ANDROID_LOG_DEBUG, VPN_TAG, "Pending conns: %u/%u", proxy->cur_notif_pending, proxy->notif_pending_size);
/* Will free the data in sendConnectionsDump */
return;
}
free_connection_data(data);
}
/* ******************************************************* */
@ -619,6 +657,7 @@ static int connection_dumper(zdtun_t *tun, const zdtun_conn_t *conn_info, void *
/* Add the connection to the array */
(*env)->SetObjectArrayElement(env, dump_data->connections, dump_data->idx++, conn_descriptor);
data->notified = true;
/* Continue */
return(0);
@ -630,7 +669,7 @@ static void sendConnectionsDump(zdtun_t *tun, vpnproxy_data_t *proxy) {
dump_data_t dump_data = {0};
jclass vpn_service_cls = (*env)->GetObjectClass(env, proxy->vpn_service);
dump_data.num_connections = zdtun_get_num_connections(tun);
dump_data.num_connections = zdtun_get_num_connections(tun) + proxy->cur_notif_pending;
jmethodID midMethod = (*env)->GetMethodID(env, vpn_service_cls, "sendConnectionsDump",
"([Lcom/emanuelef/remote_capture/ConnDescriptor;)V");
@ -669,6 +708,21 @@ static void sendConnectionsDump(zdtun_t *tun, vpnproxy_data_t *proxy) {
/* Add connections to the array */
zdtun_iter_connections(tun, connection_dumper, &dump_data);
/* Handle possibly pending data */
if(proxy->cur_notif_pending > 0) {
__android_log_print(ANDROID_LOG_DEBUG, VPN_TAG, "Processing %u pending conns", proxy->cur_notif_pending);
for(int i = 0; i < proxy->cur_notif_pending; i++) {
connection_dumper(tun, &proxy->notif_pending[i], &dump_data);
free_connection_data(proxy->notif_pending[i].user_data);
}
/* Empty the pending notifications list */
free(proxy->notif_pending);
proxy->notif_pending = NULL;
proxy->cur_notif_pending = proxy->notif_pending_size = 0;
}
/* Send the dump */
(*env)->CallVoidMethod(env, proxy->vpn_service, midMethod, dump_data.connections);
}
@ -861,6 +915,16 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
ztdun_finalize(tun);
ndpi_exit_detection_module(proxy.ndpi);
/* Free possible pending data */
if(proxy.cur_notif_pending > 0) {
for(int i = 0; i < proxy.cur_notif_pending; i++) {
free_connection_data(proxy.notif_pending[i].user_data);
}
/* Empty the pending notifications list */
free(proxy.notif_pending);
}
if(dumper_socket > 0) {
close(dumper_socket);
dumper_socket = -1;

View File

@ -46,6 +46,9 @@ typedef struct vpnproxy_data {
u_int32_t vpn_ipv4;
bool dns_changed;
struct ndpi_detection_module_struct *ndpi;
zdtun_conn_t *notif_pending;
u_int32_t cur_notif_pending;
u_int32_t notif_pending_size;
struct {
u_int32_t collector_addr;