📄 mtp3d.c
字号:
}
return 0;
}
static void mtp_mainloop(void)
{
int res;
struct pollfd fds[MAX_LINKS*2] = {{0,}};
int n_listen = 0;
int asockets[MAX_LINKS];
int n_asockets = 0;
int rebuild_fds = 1;
int n_fds = 0;
unsigned char buf[1024];
int i, port;
ast_verbose(VERBOSE_PREFIX_3 "Starting mtp mainloop, pid=%d.\n", getpid());
for (i = 0; i < this_host->n_schannels; i++) {
struct link* link = this_host->schannels[i];
if (strcmp(link->mtp3server_host, this_host->name) == 0) {
port = atoi(link->mtp3server_port);
link->mtp3fd = mtp3_setup_socket(port, 0);
if (link->mtp3fd == -1) {
ast_log(LOG_ERROR, "Could not setup mtp3 listen port %d, %d:%s\n", port, errno, strerror(errno));
return;
}
printf("Using mtp3 service port %d, socket %d\n", port, link->mtp3fd);
n_listen++;
}
}
if (!n_listen) {
fprintf(stderr, "No signaling channels\n");
exit(1);
}
while(monitor_running) {
int timeout = 2000;
int servsock;
loop:
if (rebuild_fds) {
rebuild_fds = 0;
n_fds = 0;
for (i = 0; i < n_links; i++) {
struct link* link = &links[i];
if (link->mtp3fd > -1) {
fds[n_fds].fd = link->mtp3fd;
fds[n_fds++].events = POLLIN|POLLERR|POLLNVAL|POLLHUP;
}
}
for (i = 0; i < n_asockets; i++) {
fds[n_fds].fd = asockets[i];
fds[n_fds++].events = POLLIN|POLLERR|POLLNVAL|POLLHUP;
}
}
res = poll(fds, n_fds, timeout);
if(res < 0) {
if(errno == EINTR) {
/* Just try again. */
} else {
ast_log(LOG_ERROR, "poll() failure, errno=%d: %s\n",
errno, strerror(errno));
}
} else if(res > 0) {
servsock = -1;
for (i = 0; i < n_fds; i++)
if(fds[i].revents & (POLLIN|POLLERR|POLLNVAL|POLLHUP)) {
servsock = fds[i].fd;
break;
}
if (servsock < 0)
continue;
printf("poll fd: %d, i: %d, revent 0x%04x\n", servsock, i, fds[i].revents);
if(fds[i].revents & (POLLERR|POLLNVAL|POLLHUP)) {
if (i < n_listen) {
rebuild_fds++;
continue;
}
close_socket(servsock, asockets, &n_asockets, i-n_listen);
rebuild_fds++;
continue;
}
#if MTP3_SOCKETTYPE == SOCK_STREAM
if (i < n_listen) {
struct sockaddr_in from_addr;
unsigned int len = sizeof(struct sockaddr_in);
int afd = accept(servsock, (struct sockaddr *)&from_addr, &len);
if (afd != -1) {
ast_log(LOG_NOTICE, "Accepted socket connection from %s, fd %d\n", inet_ntoa(from_addr.sin_addr), afd);
setnonblock_fd(afd);
asockets[n_asockets++] = afd;
rebuild_fds = 1;
continue;
}
else {
ast_log(LOG_WARNING, "Accept of receiver connection failed: %s.\n", strerror(errno));
}
}
#endif
for(;;) {
struct sockaddr_in from;
socklen_t fromlen = sizeof(from);
res = recvfrom(servsock, buf, sizeof(struct mtp_req), 0, &from, &fromlen);
if(res == 0) {
/* EOF. */
close_socket(servsock, asockets, &n_asockets, i-n_listen);
rebuild_fds = 1;
break;
} else if(res < 0) {
if(errno == EAGAIN || errno == EWOULDBLOCK) {
break;
} else if(errno == EINTR) {
/* Try again. */
} else {
/* Some unexpected error. */
ast_log(LOG_WARNING, "Error reading mtp3 socket %d, errno=%d: %s.\n", servsock, errno, strerror(errno));
close_socket(servsock, asockets, &n_asockets, i-n_listen);
rebuild_fds = 1;
break;
}
} else {
struct mtp_req *req = (struct mtp_req *)buf;
#undef inet_ntoa
if (fromlen) {
if (from.sin_port == 0) {
printf("got data from invalid source %s:%d, ignoring\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port));
//xxx break;
}
printf("got data on %d %s:%d\n", servsock, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
}
else
printf("got data on %d\n", servsock);
if ((req->typ == MTP_REQ_ISUP) || (req->typ == MTP_REQ_SCCP)) {
int p = res;
do {
res = recvfrom(servsock, &buf[p], req->len, 0, &from, &fromlen);
if (res == 0) {
ast_log(LOG_WARNING, "Unexpectec EOF on mtp3 socket %d\n", servsock);
close_socket(servsock, asockets, &n_asockets, i-n_listen);
rebuild_fds = 1;
goto loop;
}
else if (res < 0) {
if(errno == EINTR) {
continue;
} else {
/* Some unexpected error. */
ast_log(LOG_WARNING, "Error reading mtp3 socket %d, errno=%d: %s.\n", servsock, errno, strerror(errno));
close_socket(servsock, asockets, &n_asockets, i-n_listen);
rebuild_fds = 1;
goto loop;
}
}
p += res;
} while ((res > 0) && (p < req->len));
}
switch (req->typ) {
case MTP_REQ_REGISTER_L4:
{
int i;
for (i = 0; i < n_registry; i++) {
if ((registry->ss7_protocol == req->regist.ss7_protocol) &&
(registry[i].host_ix == req->regist.host_ix) &&
(memcmp(®istry[i].client.sin_addr, &from.sin_addr, sizeof(from.sin_addr))== 0) &&
(registry[i].link == &links[req->regist.linkix])) {
if (registry->ss7_protocol == SS7_PROTO_ISUP) {
break; /* client re-registers, possibly with new sin_port */
} else if (registry->ss7_protocol == SS7_PROTO_ISUP)
if (registry[i].sccp.subsystem == req->regist.sccp.subsystem)
break;
}
}
if (i == n_registry)
n_registry++;
printf("got register protocol %d, link %d, clients now %d\n", req->regist.ss7_protocol, req->regist.linkix, n_registry);
if (n_registry == MAXCLIENTS-1) {
ast_log(LOG_ERROR, "Too many client connections\n");
break;
}
registry[i].ss7_protocol = req->regist.ss7_protocol;
registry[i].host_ix = req->regist.host_ix;
registry[i].peerfd = servsock;
registry[i].client = from;
if (req->regist.linkix >= n_links) {
ast_log(LOG_ERROR, "ISUP req register link_ix %d out of range, max %d\n", req->regist.linkix, n_links);
break;
}
registry[i].link = &links[req->regist.linkix];
if ((req->regist.ss7_protocol == SS7_PROTO_ISUP) ||
(req->regist.ss7_protocol == SS7_PROTO_SCCP)) {
ast_log(LOG_NOTICE, "Registered client protocol %d for link '%s'\n", req->regist.ss7_protocol, links[req->regist.linkix].name);
if (req->regist.ss7_protocol == SS7_PROTO_SCCP) {
registry[i].sccp.subsystem = req->regist.sccp.subsystem;
}
}
else
ast_log(LOG_ERROR, "Unknown req register ss7 protocol %d.\n", req->regist.ss7_protocol);
}
break;
case MTP_REQ_ISUP:
{
int i;
struct link* link;
for (i = 0; i < n_registry; i++) {
if ((memcmp((void*) ®istry[i].client, (void*) &from, sizeof(from)) == 0) &&
(registry[i].ss7_protocol == SS7_PROTO_ISUP)) {
link = registry[i].link;
if (!mtp_send_fifo) {
ast_log(LOG_ERROR, "Send fifo not ready for link '%s'\n", link->name);
break;
}
if (!mtp_send_fifo[link->linkset->lsi]) {
ast_log(LOG_ERROR, "Send fifo missing for link '%s', lsi %d\n", link->name, link->linkset->lsi);
break;
}
req->isup.link = NULL;
req->isup.slink = &links[req->isup.slinkix];
printf("got isup req, link %s, slinkix %d\n", link->name, req->isup.slinkix);
res = lffifo_put(mtp_send_fifo[req->isup.slink->linkset->lsi], (unsigned char *)req, sizeof(struct mtp_req) + req->len);
break;
}
}
if (i == n_registry) {
unsigned char buf[MTP_EVENT_MAX_SIZE];
struct mtp_event *event = (struct mtp_event*) buf;
event->typ = MTP_EVENT_REQ_REGISTER;
event->regist.ss7_protocol = SS7_PROTO_ISUP;
event->regist.isup.slinkix = req->isup.slinkix;
event->len = 0;
mtp3_reply(servsock, (void*) buf, sizeof(*event)+event->len, (const struct sockaddr*) &from, fromlen);
}
}
break;
case MTP_REQ_SCCP:
{
int i;
struct link* link;
for (i = 0; i < n_registry; i++) {
if ((memcmp((void*) ®istry[i].client, (void*) &from, sizeof(from)) == 0) &&
(registry[i].ss7_protocol == SS7_PROTO_SCCP)) {
link = &links[req->sccp.slinkix];
if (!mtp_send_fifo) {
ast_log(LOG_ERROR, "Send fifo not ready for link '%s'\n", link->name);
break;
}
if (!mtp_send_fifo[link->linkset->lsi]) {
ast_log(LOG_ERROR, "Send fifo missing for link '%s', lsi %d\n", link->name, link->linkset->lsi);
break;
}
req->sccp.slink = &links[req->sccp.slinkix];
printf("got sccp req, link %s, slinkix %d\n", link->name, req->sccp.slinkix);
res = lffifo_put(mtp_send_fifo[req->sccp.slink->linkset->lsi], (unsigned char *)req, sizeof(struct mtp_req) + req->len);
break;
}
}
if (i == n_registry) {
unsigned char buf[MTP_EVENT_MAX_SIZE];
struct mtp_event *event = (struct mtp_event*) buf;
event->typ = MTP_EVENT_REQ_REGISTER;
event->regist.ss7_protocol = SS7_PROTO_SCCP;
event->len = 0;
mtp3_reply(servsock, (void*) buf, sizeof(*event)+event->len, (const struct sockaddr*) &from, fromlen);
}
}
break;
default:
ast_log(LOG_NOTICE, "Unknown req type %d.\n", req->typ);
break;
}
}
}
}
}
}
static void setup_dump(const char* fn)
{
FILE *fh;
fh = fopen(fn, "w");
if(fh == NULL) {
fprintf(stderr, "Error opening file '%s': %s.\n", fn, strerror(errno));
return;
}
dump_in_fh = fh;
dump_out_fh = fh;
dump_do_fisu = 0;
dump_do_lssu = 0;
dump_do_msu = 1;
init_pcap_file(fh);
}
static void usage(void)
{
fprintf(stderr, "usage: mtp3d [-c <configdir>] [-m <protocol-dump-file>] [-d] [-p]\n");
exit(1);
}
static void sigterm(int p)
{
monitor_running = 0;
}
static int setup_daemon(void)
{
FILE* pidfile = fopen("/var/run/mtp3d.pid", "w");
if (!pidfile) {
fprintf(stderr, "Cannot open /var/run/mtp3d.pid %d: %s\n", errno, strerror(errno));
return 1;
}
signal(SIGTERM, sigterm);
fprintf(pidfile, "%d\n", getpid());
fclose(pidfile);
return 0;
}
int main(int argc, char* argv[])
{
char dumpfn[PATH_MAX] = {0,};
int c;
strcpy(ast_config_AST_CONFIG_DIR, "/etc/asterisk");
while ((c = getopt(argc, argv, "c:m:dp")) != -1) {
switch (c) {
case 'c':
strcpy(ast_config_AST_CONFIG_DIR, optarg);
break;
case 'm':
strcpy(dumpfn, optarg);
break;
case 'd':
option_debug++;
break;
case 'p':
do_pid = 1;
break;
default:
usage();
}
}
is_mtp3d = 1;
printf("Using %s for config directory\n", ast_config_AST_CONFIG_DIR);
if(load_config(0)) {
return -1;
}
if (*dumpfn)
setup_dump(dumpfn);
if (do_pid)
if (setup_daemon())
return -1;
if(mtp_init()) {
ast_log(LOG_ERROR, "Unable to initialize MTP.\n");
return -1;
}
if(start_mtp_thread()) {
ast_log(LOG_ERROR, "Unable to start MTP thread.\n");
return -1;
}
mtp_control_fifo = mtp_get_control_fifo();
monitor_running = 1; /* Otherwise there is a race, and
monitor may exit immediately */
if(pthread_create(&monitor_thread, NULL, monitor_main, NULL) < 0) {
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
monitor_running = 0;
return -1;
}
mtp_mainloop();
stop_mtp_thread();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -