Newer
Older
ast_channel_unlock(c0);
ast_channel_unlock(c1);
Matthew Fredrickson
committed
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);
Matthew Fredrickson
committed
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));
Matthew Fredrickson
committed
} else {
/* Store UDPTL peer */
ast_udptl_get_peer(p1, &ac1);
}
if (pr1->set_udptl_peer(c1, p0)) {
Matthew Fredrickson
committed
ast_log(LOG_WARNING, "Channel '%s' failed to talk back to '%s'\n", c1->name, c0->name);
memset(&ac0, 0, sizeof(ac0));
} else {
Matthew Fredrickson
committed
/* Store UDPTL peer */
ast_udptl_get_peer(p0, &ac0);
}
ast_channel_unlock(c0);
ast_channel_unlock(c1);
Matthew Fredrickson
committed
cs[0] = c0;
cs[1] = c1;
cs[2] = NULL;
for (;;) {
Matthew Fredrickson
committed
(c1->tech_pvt != pvt1) ||
(c0->masq || c0->masqr || c1->masq || c1->masqr)) {
ast_debug(1, "Oooh, something is weird, backing out\n");
Matthew Fredrickson
committed
/* 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));
Matthew Fredrickson
committed
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));
Matthew Fredrickson
committed
memcpy(&ac0, &t0, sizeof(ac0));
}
who = ast_waitfor_n(cs, 2, &to);
if (!who) {
Matthew Fredrickson
committed
/* 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");
Matthew Fredrickson
committed
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
/* 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)
Matthew Fredrickson
committed
{
struct hostent *hp;
struct ast_hostent ahp;
int port;
char *p;
char *arg;
switch (cmd) {
case CLI_INIT:
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";
return NULL;
case CLI_GENERATE:
return NULL;
}
if (a->argc < 2 || a->argc > 4)
return CLI_SHOWUSAGE;
Matthew Fredrickson
committed
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
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;
Matthew Fredrickson
committed
}
return CLI_SUCCESS;
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;
switch (cmd) {
case CLI_INIT:
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";
return NULL;
case CLI_GENERATE:
return NULL;
}
Matthew Fredrickson
committed
if (a->argc < 4 || a->argc > 5)
return CLI_SHOWUSAGE;
Matthew Fredrickson
committed
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
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;
}
Matthew Fredrickson
committed
return CLI_SUCCESS;
}
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)
Matthew Fredrickson
committed
static void __ast_udptl_reload(int reload)
Matthew Fredrickson
committed
{
struct ast_config *cfg;
Tilghman Lesher
committed
const char *s;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
if ((cfg = ast_config_load("udptl.conf", config_flags)) == CONFIG_STATUS_FILEUNCHANGED)
return;
Matthew Fredrickson
committed
udptlstart = 4500;
udptlend = 4999;
udptlfectype = 0;
udptlfecentries = 0;
udptlfecspan = 0;
udptlmaxdatagram = 0;
Matthew Fredrickson
committed
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
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);
Matthew Fredrickson
committed
}
void ast_udptl_reload(void)
{
__ast_udptl_reload(1);
}
Matthew Fredrickson
committed
void ast_udptl_init(void)
{
ast_cli_register_multiple(cli_udptl, sizeof(cli_udptl) / sizeof(struct ast_cli_entry));
__ast_udptl_reload(0);