Add Waiting for multicast packet mode.

This commit is contained in:
Taeho Oh 2016-02-22 09:29:39 +09:00
parent 59f4f8653f
commit 3c969575fd

View File

@ -17,6 +17,7 @@ static gint _omvs_jobs = 1;
static gint _omvs_sleep = 1000;
static gint _omvs_timeout = 10000;
static gboolean _omvs_quiet;
static gboolean _omvs_wait;
static gchar **_omvs_net_dev_names;
static gchar **_omvs_net_dev_descs;
@ -38,6 +39,8 @@ static GOptionEntry _omvs_entries[] =
"Timeout time(milliseconds) in each scan", "ms" },
{ "quiet", 'q', 0, G_OPTION_ARG_NONE, &_omvs_quiet,
"Print no log except for errors", NULL },
{ "wait", 'w', 0, G_OPTION_ARG_NONE, &_omvs_wait,
"Wait for multicast packet", NULL },
{ NULL }
};
@ -84,6 +87,7 @@ static gint _omvs_print_net_devs_info(void);
static gint _omvs_deinit_net_devs_info(void);
static gint _omvs_start_scan(OMVSScanner *scanner);
static gpointer _omvs_start_scan_job(gpointer data);
static gint _omvs_wait_for_multicast_packet(void);
static gint _omvs_init_net_devs_info(void) {
gchar errbuf[PCAP_ERRBUF_SIZE];
@ -198,7 +202,7 @@ static gpointer _omvs_start_scan_job(gpointer data) {
addr[3] = (guint8)((o_ipaddr->addr >> 0) & 0xff);
addr_str =
g_strdup_printf("%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
g_strdup_printf("%u.%u.%u.%u", addr[0], addr[1], addr[2], addr[3]);
if (!_omvs_quiet) {
g_print("[%p] start scanning %s\n", (void *)g_thread_self(), addr_str);
@ -392,6 +396,153 @@ static gint _omvs_start_scan(OMVSScanner *scanner) {
return 0;
}
static gint _omvs_wait_for_multicast_packet(void) {
pcap_t *pcap;
gchar errbuf[PCAP_ERRBUF_SIZE];
const guint8 *packet;
struct pcap_pkthdr *header;
GHashTable *urihashtable;
gint64 time1, time2;
OMVSGst gst;
gchar *cur_uri;
pcap = pcap_open_live(_omvs_net_dev_names[_omvs_net_dev_idx],
sizeof(OMVSEthHdr) + sizeof(OMVSIPHdr) + sizeof(OMVSUDPHdr),
TRUE, 500, errbuf);
if (pcap == NULL) {
g_printerr("[%p] can't open pcap: %s\n", (void *)g_thread_self(), errbuf);
goto finish_return2;
}
if (pcap_datalink(pcap) != DLT_EN10MB) {
g_printerr("[%p] %s is not ethernet\n", (void *)g_thread_self(),
_omvs_net_dev_names[_omvs_net_dev_idx]);
goto finish_return3;
}
gst = NULL;
urihashtable = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
time1 = g_get_monotonic_time();
for (;;) {
gint ret;
guint caplen;
OMVSIPHdr *ip;
OMVSUDPHdr *udp;
guint ip_hdr_len;
gint udp_port;
GInetAddress *addr;
gchar *addr_str;
guint32 haddr;
gchar *uri;
gchar *filename;
ret = pcap_next_ex(pcap, &header, &packet);
if (ret < 0) {
break;
}
if (gst) {
time2 = g_get_monotonic_time();
if (omvs_gst_is_finished(gst)) {
if (!_omvs_quiet) {
g_print("[%p] finish scanning %s\n", (void *)g_thread_self(),
cur_uri);
}
omvs_gst_close(gst);
gst = NULL;
} else if (time2 - time1 > (gint64)((gint64)_omvs_timeout * 1000)) {
if (!_omvs_quiet) {
g_print("[%p] finish scanning %s\n", (void *)g_thread_self(),
cur_uri);
}
omvs_gst_close(gst);
gst = NULL;
} else {
continue;
}
}
if (ret == 0) {
continue;
}
caplen = header->caplen;
if (caplen < sizeof(OMVSEthHdr)) {
continue;
}
packet += sizeof(OMVSEthHdr);
caplen -= sizeof(OMVSEthHdr);
if (caplen < sizeof(OMVSIPHdr)) {
continue;
}
ip = (OMVSIPHdr *)packet;
ip_hdr_len = (ip->vhl & 0x0f) * 4;
if (caplen < ip_hdr_len) {
continue;
}
if (ip->protocol != _OMVS_IPPROTO_UDP) {
continue;
}
addr = g_inet_address_new_from_bytes(
(const guint8 *)&ip->daddr, G_SOCKET_FAMILY_IPV4);
if (!g_inet_address_get_is_multicast(addr)) {
g_object_unref(addr);
continue;
}
g_object_unref(addr);
packet += ip_hdr_len;
caplen -= ip_hdr_len;
if (caplen < sizeof(OMVSUDPHdr)) {
continue;
}
udp = (OMVSUDPHdr *)packet;
udp_port = g_ntohs(udp->uh_dport);
haddr = g_ntohl(ip->daddr);
addr_str = g_strdup_printf("%u.%u.%u.%u",
(haddr >> 24) & 0xff,
(haddr >> 16) & 0xff,
(haddr >> 8) & 0xff,
(haddr >> 0) & 0xff);
uri = g_strdup_printf("udp://%s:%u", addr_str, udp_port);
filename =
g_strdup_printf("%s/%s-%d.png", _omvs_outdir, addr_str, udp_port);
g_free(addr_str);
if (!g_hash_table_insert(urihashtable, uri, NULL)) {
continue;
}
cur_uri = uri;
if (!_omvs_quiet) {
g_print("[%p] start scanning %s\n", (void *)g_thread_self(), cur_uri);
g_print("[%p] trying to save %s to %s\n", (void *)g_thread_self(),
cur_uri, filename);
}
time1 = g_get_monotonic_time();
g_assert(gst == NULL);
gst = omvs_gst_open(cur_uri, filename);
}
g_hash_table_destroy(urihashtable);
return 0;
finish_return3:
pcap_close(pcap);
finish_return2:
return -1;
}
int main(int argc, char *argv[]) {
GError *error = NULL;
GOptionContext *context;
@ -428,7 +579,7 @@ int main(int argc, char *argv[]) {
goto finish_return;
}
if (argc < 2 || _omvs_net_dev_idx >= _omvs_num_net_devs) {
if ((!_omvs_wait && argc < 2) || _omvs_net_dev_idx >= _omvs_num_net_devs) {
gchar *help_msg;
help_msg = g_option_context_get_help(context, TRUE, NULL);
g_print("%s", help_msg);
@ -439,6 +590,11 @@ int main(int argc, char *argv[]) {
g_mkdir(_omvs_outdir, 0755);
if (_omvs_wait) {
_omvs_wait_for_multicast_packet();
goto finish_return;
}
num_ipaddrs = 0;
for (i = 1; i < argc; i++) {
GInetAddressMask *mask;