📄 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 + -