Example #1
0
static int visdn_ppp_exec(struct cw_channel *chan, int argc, char **argv)
{
	struct visdn_chan *visdn_chan;
	const char **nargv;
	struct localuser *u;
	struct cw_frame *f;
	int res=-1;

	LOCAL_USER_ADD(u);

	if (chan->_state != CW_STATE_UP)
		cw_answer(chan);

	cw_mutex_lock(&chan->lock);

	if (strcmp(chan->type, "VISDN")) {
		cw_log(LOG_WARNING,
			"Only VISDN channels may be connected to"
			" this application\n");

		cw_mutex_unlock(&chan->lock);
		return -1;
	}

	visdn_chan = chan->tech_pvt;

	if (!strlen(visdn_chan->visdn_chanid)) {
		cw_log(LOG_WARNING,
			"vISDN crossconnector channel ID not present\n");
		cw_mutex_unlock(&chan->lock);
		return -1;
	}

	nargv = alloca((2 + argc + 3 + 1) * sizeof(nargv[0]));
	nargv[0] = PPP_EXEC;
	nargv[1] = "nodetach";
	memcpy(nargv + 2, argc, argv * sizeof(argv[0]));
	nargv[2 + argc + 0] = "plugin";
	nargv[2 + argc + 1] = "visdn.so";
	nargv[2 + argc + 2] = visdn_chan->visdn_chanid;
	nargv[2 + argc + 3] = NULL;

	cw_mutex_unlock(&chan->lock);

#if 0
	int i;
	for (i=0;i<argc;i++) {
		cw_log(LOG_NOTICE, "Arg %d: %s\n", i, argv[i]);
	}
#endif

	signal(SIGCHLD, SIG_DFL);

	pid_t pid = spawn_ppp(chan, nargv);
	if (pid < 0) {
		cw_log(LOG_WARNING, "Failed to spawn pppd\n");
		return -1;
	}

	while(cw_waitfor(chan, -1) > -1) {

		f = cw_read(chan);
		if (!f) {
			cw_log(LOG_NOTICE,
				"Channel '%s' hungup."
				" Signalling PPP at %d to die...\n",
				chan->name, pid);

			kill(pid, SIGTERM);

			break;
		}

		cw_fr_free(f);

		int status;
		res = wait4(pid, &status, WNOHANG, NULL);
		if (res < 0) {
			cw_log(LOG_WARNING,
				"wait4 returned %d: %s\n",
				res, strerror(errno));

			break;
		} else if (res > 0) {
			if (option_verbose > 2) {
				if (WIFEXITED(status)) {
					cw_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated with status %d\n",
						chan->name, WEXITSTATUS(status));
				} else if (WIFSIGNALED(status)) {
					cw_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated with signal %d\n", 
						chan->name, WTERMSIG(status));
				} else {
					cw_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated weirdly.\n", chan->name);
				}
			}

			break;
		}
	}

	LOCAL_USER_REMOVE(u);
	return res;
}
Example #2
0
static int visdn_ppp_exec(struct ast_channel *chan, void *data)
{
	int res=-1;
	struct ast_frame *f;

	if (chan->_state != AST_STATE_UP)
		ast_answer(chan);

	ast_mutex_lock(&chan->lock);

#if ASTERISK_VERSION_NUM < 010400 || (ASTERISK_VERSION_NUM >= 10200 && ASTERISK_VERSION_NUM < 10400)
	if (strcmp(chan->type, "VISDN")) {
#else
	if (strcmp(chan->tech->type, "VISDN")) {
#endif
		ast_log(LOG_WARNING,
			"Only VISDN channels may be connected to"
			" this application\n");

		ast_mutex_unlock(&chan->lock);
		return -1;
	}

	struct visdn_chan *visdn_chan = to_visdn_chan(chan);

	if (!visdn_chan->node_bearer) {
		ast_log(LOG_WARNING,
			"vISDN bearer channel not present\n");
		ast_mutex_unlock(&chan->lock);
		return -1;
	}

	const char *argv[PPP_MAX_ARGS] = { };
	int argc = 0;

	argv[argc++] = PPP_EXEC;
	argv[argc++] = "nodetach";

	char *stringp = strdup(data);
	char *arg;
	while((arg = strsep(&stringp, "|"))) {

		if (!strlen(arg))
			break;

		if (argc >= PPP_MAX_ARGS - 4)
			break;

		argv[argc++] = arg;
	}

	char chan_id_arg[10];
	snprintf(chan_id_arg, sizeof(chan_id_arg),
		"%06d", visdn_chan->node_bearer->id);

	argv[argc++] = "plugin";
	argv[argc++] = "visdn.so";
	argv[argc++] = chan_id_arg;

	ast_mutex_unlock(&chan->lock);

#if 0
	int i;
	for (i=0;i<argc;i++) {
		ast_log(LOG_NOTICE, "Arg %d: %s\n", i, argv[i]);
	}
#endif

	signal(SIGCHLD, SIG_DFL);

	pid_t pid = spawn_ppp(chan, argv, argc);
	if (pid < 0) {
		ast_log(LOG_WARNING, "Failed to spawn pppd\n");
		return -1;
	}

	while(ast_waitfor(chan, -1) > -1) {

		f = ast_read(chan);
		if (!f) {
			ast_log(LOG_NOTICE,
				"Channel '%s' hungup."
				" Signalling PPP at %d to die...\n",
				chan->name, pid);

			kill(pid, SIGTERM);

			break;
		}

		ast_frfree(f);

		int status;
		res = wait4(pid, &status, WNOHANG, NULL);
		if (res < 0) {
			ast_log(LOG_WARNING,
				"wait4 returned %d: %s\n",
				res, strerror(errno));

			break;
		} else if (res > 0) {
			if (option_verbose > 2) {
				if (WIFEXITED(status)) {
					ast_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated with "
						"status %d\n",
						chan->name,
						WEXITSTATUS(status));

				} else if (WIFSIGNALED(status)) {
					ast_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated with "
						"signal %d\n", 
						chan->name,
						WTERMSIG(status));
				} else {
					ast_verbose(VERBOSE_PREFIX_3
						"PPP on %s terminated "
						"weirdly.\n", chan->name);
				}
			}

			break;
		}
	}

	return res;
}

int visdn_ppp_load_module(void)
{
	return ast_register_application(
			VISDN_PPP_APP_NAME,
			visdn_ppp_exec,
			"Runs pppd and connects channel to visdn-ppp gateway",
			descrip);
}

int visdn_ppp_unload_module(void)
{
	return ast_unregister_application(VISDN_PPP_APP_NAME);
}