[FEATURE] Support for Source-Specific Multicast (#802)

* Support for Source-Specific Multicast

* fixing whitespace issues

* updating changelog
This commit is contained in:
Chuck Wilson 2017-12-24 00:10:14 -05:00 committed by Carlos Fernandez Sanz
parent 44a9e8b2af
commit 59b8f81283
9 changed files with 81 additions and 10 deletions

View File

@ -1,3 +1,7 @@
0.87
-----------------
- New: Support for source-specific multicast.
0.86
-----------------
- New: Added a histogram in one-minute increments of the number of lines in a subtitle.

View File

@ -48,7 +48,7 @@ void draw_network_popup(struct nk_context *ctx, struct network_popup *network_se
nk_label(ctx, "UDP:", NK_TEXT_CENTERED);
nk_layout_row_static(ctx, 20, 200, 2);
nk_label(ctx, "Hostname/IPv4 Address:", NK_TEXT_LEFT);
nk_edit_string(ctx, NK_EDIT_SIMPLE, network_settings->udp_ipv4, &network_settings->udp_ipv4_len, 25, nk_filter_default);
nk_edit_string(ctx, NK_EDIT_SIMPLE, network_settings->udp_ipv4, &network_settings->udp_ipv4_len, 50, nk_filter_default);
nk_layout_row(ctx, NK_DYNAMIC, 21, 3, udp_tcp_ratio);
nk_spacing(ctx, 1);

View File

@ -90,6 +90,7 @@ void init_options (struct ccx_s_options *options)
options->debug_mask=CCX_DMT_GENERIC_NOTICES; // dbg_print will use this mask to print or ignore different types
options->debug_mask_on_debug=CCX_DMT_VERBOSE; // If we're using temp_debug to enable/disable debug "live", this is the mask when temp_debug=1
/* Networking */
options->udpsrc = NULL;
options->udpaddr = NULL;
options->udpport=0; // Non-zero => Listen for UDP packets on this port, no files.
options->send_to_srv = 0;

View File

@ -157,6 +157,7 @@ struct ccx_s_options // Options from user parameters
LLONG debug_mask; // dbg_print will use this mask to print or ignore different types
LLONG debug_mask_on_debug; // If we're using temp_debug to enable/disable debug "live", this is the mask when temp_debug=1
/* Networking */
char *udpsrc;
char *udpaddr;
unsigned udpport; // Non-zero => Listen for UDP packets on this port, no files.
char *tcpport;

View File

@ -78,7 +78,7 @@ static int ccx_demuxer_open(struct ccx_demuxer *ctx, const char *file)
return -1;
}
ctx->infd = start_upd_srv(ccx_options.udpaddr, ccx_options.udpport);
ctx->infd = start_upd_srv(ccx_options.udpsrc, ccx_options.udpaddr, ccx_options.udpport);
if(ctx->infd < 0)
{
print_error(ccx_options.gui_mode_reports,"socket() failed.");

View File

@ -927,10 +927,28 @@ ssize_t read_byte(int fd, char *ch)
return readn(fd, ch, 1);
}
int start_upd_srv(const char *addr_str, unsigned port)
int start_upd_srv(const char *src_str, const char *addr_str, unsigned port)
{
init_sockets();
in_addr_t src;
if (src_str != NULL)
{
struct hostent *host = gethostbyname(src_str);
if (NULL == host)
{
fatal(EXIT_MALFORMED_PARAMETER, "Cannot look up udp network address: %s\n",
src_str);
}
else if (host->h_addrtype != AF_INET)
{
fatal(EXIT_MALFORMED_PARAMETER, "No support for non-IPv4 network addresses: %s\n",
src_str);
}
src = ntohl(((struct in_addr *)host->h_addr_list[0])->s_addr);
}
in_addr_t addr;
if (addr_str != NULL)
{
@ -1000,10 +1018,23 @@ int start_upd_srv(const char *addr_str, unsigned port)
}
if (IN_MULTICAST(addr)) {
struct ip_mreq group;
group.imr_multiaddr.s_addr = htonl(addr);
group.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0)
int setsockopt_return = 0;
if (src_str != NULL) {
struct ip_mreq_source multicast_req;
multicast_req.imr_sourceaddr.s_addr = htonl(src);
multicast_req.imr_multiaddr.s_addr = htonl(addr);
multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt_return = setsockopt(sockfd, IPPROTO_IP, IP_ADD_SOURCE_MEMBERSHIP, (char *)&multicast_req, sizeof(multicast_req));
}
else
{
struct ip_mreq multicast_req;
multicast_req.imr_multiaddr.s_addr = htonl(addr);
multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt_return = setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&multicast_req, sizeof(multicast_req));
}
if (setsockopt_return < 0)
{
#if _WIN32
wprintf(L"setsockopt() error: %ld\n", WSAGetLastError());
@ -1019,6 +1050,21 @@ int start_upd_srv(const char *addr_str, unsigned port)
{
mprint("\rReading from UDP socket %u\n", port);
}
else if (src_str != NULL)
{
struct in_addr source;
struct in_addr group;
char src_ip[15];
char addr_ip[15];
source.s_addr = htonl(src);
memset(src_ip, 0, sizeof(char) * 15);
memcpy(src_ip, inet_ntoa(source), sizeof(src_ip));
group.s_addr = htonl(addr);
memset(addr_ip, 0, sizeof(char) * 15);
memcpy(addr_ip, inet_ntoa(group), sizeof(addr_ip));
mprint("\rReading from UDP socket %s@%s:%u\n", src_ip, addr_ip, port);
}
else
{
struct in_addr in;

View File

@ -23,6 +23,6 @@ int net_tcp_read(int socket, void *buffer, size_t length);
int start_tcp_srv(const char *port, const char *pwd);
int start_upd_srv(const char *addr, unsigned port);
int start_upd_srv(const char *src, const char *addr, unsigned port);
#endif /* end of include guard: NETWORKING_H */

View File

@ -335,6 +335,10 @@ void print_usage (void)
mprint (" port) instead of reading a file. Host can be a\n");
mprint (" hostname or IPv4 address. If host is not specified\n");
mprint (" then listens on the local host.\n\n");
mprint (" -udp [src@host:]port: Read the input via UDP (listening in the specified\n");
mprint (" port) instead of reading a file. Host and src can be a\n");
mprint (" hostname or IPv4 address. If host is not specified\n");
mprint (" then listens on the local host.\n\n");
mprint (" -sendto host[:port]: Sends data in BIN format to the server\n");
mprint (" according to the CCExtractor's protocol over\n");
mprint (" TCP. For IPv6 use [address]:port\n");
@ -2220,8 +2224,21 @@ int parse_parameters (struct ccx_s_options *opt, int argc, char *argv[])
/* Network stuff */
if (strcmp (argv[i],"-udp")==0 && i<argc-1)
{
char *at = strchr(argv[i + 1], '@');
char *colon = strchr(argv[i + 1], ':');
if (colon)
if (at && !colon)
{
fatal(EXIT_MALFORMED_PARAMETER, "If -udp contains an '@', it must also contain a ':'");
}
else if (at && colon)
{
*at = '\0';
*colon = '\0';
opt->udpsrc = argv[i + 1];
opt->udpaddr = at + 1;
opt->udpport = atoi_hex(colon + 1);
}
else if (colon)
{
*colon = '\0';
opt->udpaddr = argv[i + 1];

View File

@ -18,7 +18,9 @@ void params_dump(struct lib_ccx_ctx *ctx)
mprint ("stdin");
break;
case CCX_DS_NETWORK:
if (ccx_options.udpaddr == NULL)
if (ccx_options.udpsrc != NULL)
mprint ("Network, %s@%s:%d", ccx_options.udpsrc, ccx_options.udpaddr, ccx_options.udpport);
else if (ccx_options.udpaddr == NULL)
mprint ("Network, UDP/%u",ccx_options.udpport);
else
{