Skip to content
Snippets Groups Projects
udptl.c 34.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		ast_channel_unlock(c0);
    		ast_channel_unlock(c1);
    
    		return -1;
    	}
    	pvt0 = c0->tech_pvt;
    	pvt1 = c1->tech_pvt;
    	p0 = pr0->get_udptl_info(c0);
    	p1 = pr1->get_udptl_info(c1);
    	if (!p0 || !p1) {
    		/* Somebody doesn't want to play... */
    
    		ast_channel_unlock(c0);
    		ast_channel_unlock(c1);
    
    		return -2;
    	}
    	if (pr0->set_udptl_peer(c0, p1)) {
    		ast_log(LOG_WARNING, "Channel '%s' failed to talk to '%s'\n", c0->name, c1->name);
    
    		memset(&ac1, 0, sizeof(ac1));
    
    	} else {
    		/* Store UDPTL peer */
    		ast_udptl_get_peer(p1, &ac1);
    	}
    
    	if (pr1->set_udptl_peer(c1, p0)) {
    
    		ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
    
    		memset(&ac0, 0, sizeof(ac0));
    	} else {
    
    		/* Store UDPTL peer */
    		ast_udptl_get_peer(p0, &ac0);
    	}
    
    	ast_channel_unlock(c0);
    	ast_channel_unlock(c1);
    
    Tilghman Lesher's avatar
    Tilghman Lesher committed
    		if ((c0->tech_pvt != pvt0) ||
    
    			(c1->tech_pvt != pvt1) ||
    			(c0->masq || c0->masqr || c1->masq || c1->masqr)) {
    
    				ast_debug(1, "Oooh, something is weird, backing out\n");
    
    				/* Tell it to try again later */
    				return -3;
    		}
    		to = -1;
    		ast_udptl_get_peer(p1, &t1);
    		ast_udptl_get_peer(p0, &t0);
    		if (inaddrcmp(&t1, &ac1)) {
    
    			ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 
    				c1->name, ast_inet_ntoa(t1.sin_addr), ntohs(t1.sin_port));
    			ast_debug(1, "Oooh, '%s' was %s:%d\n", 
    				c1->name, ast_inet_ntoa(ac1.sin_addr), ntohs(ac1.sin_port));
    
    			memcpy(&ac1, &t1, sizeof(ac1));
    		}
    		if (inaddrcmp(&t0, &ac0)) {
    
    			ast_debug(1, "Oooh, '%s' changed end address to %s:%d\n", 
    				c0->name, ast_inet_ntoa(t0.sin_addr), ntohs(t0.sin_port));
    			ast_debug(1, "Oooh, '%s' was %s:%d\n", 
    				c0->name, ast_inet_ntoa(ac0.sin_addr), ntohs(ac0.sin_port));
    
    			memcpy(&ac0, &t0, sizeof(ac0));
    		}
    		who = ast_waitfor_n(cs, 2, &to);
    		if (!who) {
    
    			ast_debug(1, "Ooh, empty read...\n");
    
    			/* check for hangup / whentohangup */
    			if (ast_check_hangup(c0) || ast_check_hangup(c1))
    				break;
    			continue;
    		}
    		f = ast_read(who);
    		if (!f) {
    			*fo = f;
    			*rc = who;
    
    			ast_debug(1, "Oooh, got a %s\n", f ? "digit" : "hangup");
    
    			/* That's all we needed */
    			return 0;
    		} else {
    			if (f->frametype == AST_FRAME_MODEM) {
    				/* Forward T.38 frames if they happen upon us */
    				if (who == c0) {
    					ast_write(c1, f);
    				} else if (who == c1) {
    					ast_write(c0, f);
    				}
    			}
    			ast_frfree(f);
    		}
    		/* Swap priority. Not that it's a big deal at this point */
    		cs[2] = cs[0];
    		cs[0] = cs[1];
    		cs[1] = cs[2];
    	}
    	return -1;
    }
    
    
    static char *handle_cli_udptl_debug_deprecated(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    
    {
    	struct hostent *hp;
    	struct ast_hostent ahp;
    	int port;
    	char *p;
    	char *arg;
    
    
    		e->command = "udptl debug [off|ip]";
    		e->usage = 
    			"Usage: udptl debug [off]|[ip host[:port]]\n"
    			"       Enable or disable dumping of UDPTL packets.\n"
    			"       If ip is specified, limit the dumped packets to those to and from\n"
    			"       the specified 'host' with optional port.\n";
    
    	if (a->argc < 2 || a->argc > 4)
    
    	if (a->argc == 2) { 
    		udptldebug = 1;
    		memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
    		ast_cli(a->fd, "UDPTL Debugging Enabled\n");
    	} else if (a->argc == 3) {
    		if (strncasecmp(a->argv[2], "off", 3))
    			return CLI_SHOWUSAGE;
    		udptldebug = 0;
    		ast_cli(a->fd, "UDPTL Debugging Disabled\n");
    	} else {
    		if (strncasecmp(a->argv[2], "ip", 2))
    			return CLI_SHOWUSAGE;
    		port = 0;
    		arg = a->argv[3];
    		p = strstr(arg, ":");
    		if (p) {
    			*p = '\0';
    			p++;
    			port = atoi(p);
    		}
    		hp = ast_gethostbyname(arg, &ahp);
    		if (hp == NULL)
    			return CLI_SHOWUSAGE;
    		udptldebugaddr.sin_family = AF_INET;
    		memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
    		udptldebugaddr.sin_port = htons(port);
    		if (port == 0)
    			ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
    		else
    			ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
    		udptldebug = 1;
    
    static char *handle_cli_udptl_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
    
    	struct hostent *hp;
    	struct ast_hostent ahp;
    	int port;
    	char *p;
    	char *arg;
    
    
    		e->command = "udptl set debug {on|off|ip}";
    		e->usage = 
    			"Usage: udptl set debug {on|off|ip host[:port]}\n"
    			"       Enable or disable dumping of UDPTL packets.\n"
    			"       If ip is specified, limit the dumped packets to those to and from\n"
    			"       the specified 'host' with optional port.\n";
    
    	if (a->argc < 4 || a->argc > 5)
    
    	if (a->argc == 4) {
    		if (!strncasecmp(a->argv[3], "on", 2)) {
    			udptldebug = 1;
    			memset(&udptldebugaddr, 0, sizeof(udptldebugaddr));
    			ast_cli(a->fd, "UDPTL Debugging Enabled\n");
    		} else if (!strncasecmp(a->argv[3], "off", 3)) {
    			udptldebug = 0;
    			ast_cli(a->fd, "UDPTL Debugging Disabled\n");
    		} else {
    			return CLI_SHOWUSAGE;
    		}
    	} else {
    		if (strncasecmp(a->argv[3], "ip", 2))
    			return CLI_SHOWUSAGE;
    		port = 0;
    		arg = a->argv[4];
    		p = strstr(arg, ":");
    		if (p) {
    			*p = '\0';
    			p++;
    			port = atoi(p);
    		}
    		hp = ast_gethostbyname(arg, &ahp);
    		if (hp == NULL)
    			return CLI_SHOWUSAGE;
    		udptldebugaddr.sin_family = AF_INET;
    		memcpy(&udptldebugaddr.sin_addr, hp->h_addr, sizeof(udptldebugaddr.sin_addr));
    		udptldebugaddr.sin_port = htons(port);
    		if (port == 0)
    			ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s\n", ast_inet_ntoa(udptldebugaddr.sin_addr));
    		else
    			ast_cli(a->fd, "UDPTL Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(udptldebugaddr.sin_addr), port);
    		udptldebug = 1;
    	}
    
    static struct ast_cli_entry cli_handle_udptl_debug_deprecated = AST_CLI_DEFINE(handle_cli_udptl_debug_deprecated, "Enable/Disable UDPTL debugging");
    
    
    static struct ast_cli_entry cli_udptl[] = {
    
    	AST_CLI_DEFINE(handle_cli_udptl_set_debug, "Enable/Disable UDPTL debugging", .deprecate_cmd = &cli_handle_udptl_debug_deprecated)
    
    static void __ast_udptl_reload(int reload)
    
    	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
    
    	if ((cfg = ast_config_load("udptl.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
    		return;
    
    
    	udptlstart = 4500;
    	udptlend = 4999;
    	udptlfectype = 0;
    	udptlfecentries = 0;
    	udptlfecspan = 0;
    	udptlmaxdatagram = 0;
    
    
    		if ((s = ast_variable_retrieve(cfg, "general", "udptlstart"))) {
    			udptlstart = atoi(s);
    			if (udptlstart < 1024)
    				udptlstart = 1024;
    			if (udptlstart > 65535)
    				udptlstart = 65535;
    		}
    		if ((s = ast_variable_retrieve(cfg, "general", "udptlend"))) {
    			udptlend = atoi(s);
    			if (udptlend < 1024)
    				udptlend = 1024;
    			if (udptlend > 65535)
    				udptlend = 65535;
    		}
    		if ((s = ast_variable_retrieve(cfg, "general", "udptlchecksums"))) {
    #ifdef SO_NO_CHECK
    			if (ast_false(s))
    				nochecksums = 1;
    			else
    				nochecksums = 0;
    #else
    			if (ast_false(s))
    				ast_log(LOG_WARNING, "Disabling UDPTL checksums is not supported on this operating system!\n");
    #endif
    		}
    		if ((s = ast_variable_retrieve(cfg, "general", "T38FaxUdpEC"))) {
    			if (strcmp(s, "t38UDPFEC") == 0)
    				udptlfectype = 2;
    			else if (strcmp(s, "t38UDPRedundancy") == 0)
    				udptlfectype = 1;
    		}
    		if ((s = ast_variable_retrieve(cfg, "general", "T38FaxMaxDatagram"))) {
    			udptlmaxdatagram = atoi(s);
    			if (udptlmaxdatagram < 0)
    				udptlmaxdatagram = 0;
    			if (udptlmaxdatagram > LOCAL_FAX_MAX_DATAGRAM)
    				udptlmaxdatagram = LOCAL_FAX_MAX_DATAGRAM;
    		}
    		if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECentries"))) {
    			udptlfecentries = atoi(s);
    			if (udptlfecentries < 0)
    				udptlfecentries = 0;
    			if (udptlfecentries > MAX_FEC_ENTRIES)
    				udptlfecentries = MAX_FEC_ENTRIES;
    		}
    		if ((s = ast_variable_retrieve(cfg, "general", "UDPTLFECspan"))) {
    			udptlfecspan = atoi(s);
    			if (udptlfecspan < 0)
    				udptlfecspan = 0;
    			if (udptlfecspan > MAX_FEC_SPAN)
    				udptlfecspan = MAX_FEC_SPAN;
    		}
    		ast_config_destroy(cfg);
    	}
    	if (udptlstart >= udptlend) {
    		ast_log(LOG_WARNING, "Unreasonable values for UDPTL start/end\n");
    		udptlstart = 4500;
    		udptlend = 4999;
    	}
    
    	ast_verb(2, "UDPTL allocating from port range %d -> %d\n", udptlstart, udptlend);
    
    void ast_udptl_reload(void)
    {
    	__ast_udptl_reload(1);
    }
    
    
    	ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry));