Example #1
0
static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
{
	struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri);
	zap_size_t len = buflen;
	int res;
	zap_status_t zst;

	if ((zst = zap_channel_read(spri->dchan, buf, &len)) != ZAP_SUCCESS) {
		if (zst == ZAP_FAIL) {
			zap_log(ZAP_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
			spri->errs++;
		} else {
			zap_log(ZAP_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id);
		}
		
		zap_clear_flag(spri, LPWRAP_PRI_READY);
		return -1;
	}
	spri->errs = 0;
	res = (int)len;
	memset(&((unsigned char*)buf)[res],0,2);
	res+=2;

#ifdef IODEBUG
	{
		char bb[2048] = { 0 };

		print_hex_bytes(buf, res - 2, bb, sizeof(bb));
		zap_log(ZAP_LOG_DEBUG, "READ %d\n", res-2);
	}
#endif

	return res;
}
Example #2
0
int m3uac_exec_command(m3uac_connection_t *mcon, int span, int chan, int id, int cmd, int cause)
{
    m3uac_event_t oevent;
    int retry = 5;

    m3uac_event_init(&oevent, cmd, chan, span);
    oevent.release_cause = cause;

	if (cmd == SIGBOOST_EVENT_SYSTEM_RESTART) {
		mcon->rxseq_reset = 1;
		mcon->txseq = 0;
		mcon->rxseq = 0;
		mcon->txwindow = 0;
	}

    if (id >= 0) {
        oevent.call_setup_id = id;
    }

    while (m3uac_connection_write(mcon, &oevent) <= 0) {
        if (--retry <= 0) {
            zap_log(ZAP_LOG_CRIT, "Failed to tx on M3UA socket: %s\n", strerror(errno));
            return -1;
        } else {
            zap_log(ZAP_LOG_WARNING, "Failed to tx on M3UA socket: %s :retry %i\n", strerror(errno), retry);
			zap_sleep(1);
        }
    }

    return 0;
}
Example #3
0
static zap_status_t zap_cpu_read_stats(struct zap_cpu_monitor_stats *p,
											unsigned long long *user,
											unsigned long long *nice,
											unsigned long long *system,
											unsigned long long *idle,
											unsigned long long *iowait,
											unsigned long long *irq,
											unsigned long long *softirq,
											unsigned long long *steal)
{
// the output of proc should not change that often from one kernel to other
// see fs/proc/proc_misc.c or fs/proc/stat.c in the Linux kernel for more details
// also man 5 proc is useful
#define CPU_ELEMENTS 8 // change this if you change the format string
#define CPU_INFO_FORMAT "cpu  %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu"
	static const char procfile[] = "/proc/stat";
	int rc = 0;
	int myerrno = 0;
	int elements = 0;
	const char *cpustr = NULL;
	char statbuff[1024];

	if (!p->initd) {
		p->procfd = open(procfile, O_RDONLY, 0);
		if(p->procfd == -1) {
			zap_log(ZAP_LOG_ERROR, "Failed to open CPU statistics file %s: %s\n", procfile, strerror(myerrno));
			return ZAP_FAIL;
		}
		p->initd = 1;
	} else {
		lseek(p->procfd, 0L, SEEK_SET);
	}

	rc = read(p->procfd, statbuff, sizeof(statbuff) - 1);
	if (rc <= 0) {
		myerrno = errno;
		zap_log(ZAP_LOG_ERROR, "Failed to read CPU statistics file %s: %s\n", procfile, strerror(myerrno));
		return ZAP_FAIL;
	}

	cpustr = strstr(statbuff, "cpu ");
	if (!cpustr) {
		zap_log(ZAP_LOG_ERROR, "wrong format for Linux proc cpu statistics: missing cpu string\n");
		return ZAP_FAIL;
	}

	elements = sscanf(cpustr, CPU_INFO_FORMAT, user, nice, system, idle, iowait, irq, softirq, steal);
	if (elements != CPU_ELEMENTS) {
		zap_log(ZAP_LOG_ERROR, "wrong format for Linux proc cpu statistics: expected %d elements, but just found %d\n", CPU_ELEMENTS, elements);
		return ZAP_FAIL;
	}
	return ZAP_SUCCESS;
}
OZ_DECLARE(zap_status_t) zap_interrupt_multiple_wait(zap_interrupt_t *interrupts[], zap_size_t size, int ms)
{
#ifndef WIN32
	int i;
	int res = 0;
	int numdevices = 0;
	char pipebuf[255];
	struct pollfd ints[size*2];

	memset(&ints, 0, sizeof(ints));

	for (i = 0; i < size; i++) {
		ints[i].events = POLLIN;
		ints[i].revents = 0;
		ints[i].fd = interrupts[i]->readfd;
		if (interrupts[i]->device != ZAP_INVALID_SOCKET) {
			ints[size+numdevices].events = POLLIN;
			ints[size+numdevices].revents = 0;
			ints[size+numdevices].fd = interrupts[i]->device;
			numdevices++;
		}
	}

	res = poll(ints, size + numdevices, ms);

	if (res == -1) {
		zap_log(ZAP_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno));
		return ZAP_FAIL;
	}

	if (res == 0) {
		return ZAP_TIMEOUT;
	}

	for (i = 0; i < size; i++) {
		if (ints[i].revents & POLLIN) {
			res = read(ints[i].fd, pipebuf, sizeof(pipebuf));
			if (res == -1) {
				zap_log(ZAP_LOG_CRIT, "reading interrupt descriptor failed (%s)\n", strerror(errno));
			}
		}
	}

#elif defined(__WINDOWS__)
	UNREFERENCED_PARAMETER(interrupts);
	UNREFERENCED_PARAMETER(size);
	UNREFERENCED_PARAMETER(ms);
#endif
	return ZAP_SUCCESS;
}
OZ_DECLARE(zap_status_t) zap_interrupt_signal(zap_interrupt_t *interrupt)
{
#ifdef WIN32
	if (!SetEvent(interrupt->event)) {
		zap_log(ZAP_LOG_ERROR, "Failed to signal interrupt\n");
		return ZAP_FAIL;
	}
#else
	int err;
	if ((err = write(interrupt->writefd, "w", 1)) != 1) {
		zap_log(ZAP_LOG_ERROR, "Failed to signal interrupt: %s\n", errno, strerror(errno));
		return ZAP_FAIL;
	}
#endif
	return ZAP_SUCCESS;
}
OZ_DECLARE(zap_status_t) zap_interrupt_create(zap_interrupt_t **ininterrupt, zap_socket_t device)
{
	zap_interrupt_t *interrupt = NULL;
#ifndef WIN32
	int fds[2];
#endif

	interrupt = calloc(1, sizeof(*interrupt));
	if (!interrupt) {
		zap_log(ZAP_LOG_ERROR, "Failed to allocate interrupt memory\n");
		return ZAP_FAIL;
	}

	interrupt->device = device;
#ifdef WIN32
	interrupt->event = CreateEvent(NULL, FALSE, FALSE, NULL);
	if (!interrupt->event) {
		zap_log(ZAP_LOG_ERROR, "Failed to allocate interrupt event\n");
		goto failed;
	}
#else
	if (pipe(fds)) {
		zap_log(ZAP_LOG_ERROR, "Failed to allocate interrupt pipe: %s\n", strerror(errno));
		goto failed;
	}
	
	interrupt->readfd = fds[0];
	interrupt->writefd = fds[1];
#endif

	*ininterrupt = interrupt;
	return ZAP_SUCCESS;

failed:
	if (interrupt) {
#ifndef WIN32
		if (interrupt->readfd) {
			close(interrupt->readfd);
			close(interrupt->writefd);
			interrupt->readfd = -1;
			interrupt->writefd = -1;
		}
#endif
		zap_safe_free(interrupt);
	}
	return ZAP_FAIL;
}
Example #7
0
OZ_DECLARE(zap_status_t) zap_cpu_get_system_idle_time (struct zap_cpu_monitor_stats *p, double *idle_percentage)
{
	unsigned long long user, nice, system, idle, iowait, irq, softirq, steal;
	unsigned long long usertime, kerneltime, idletime, totaltime, halftime;

	if (zap_cpu_read_stats(p, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal)) {
		zap_log(ZAP_LOG_ERROR, "Failed to retrieve Linux CPU statistics\n");
		return ZAP_FAIL;
	}

	if (!p->valid_last_times) {
		// we dont strictly need to save all of them but I feel code is more clear if we do
		p->valid_last_times = 1;
		p->last_user_time = user;
		p->last_nice_time = nice;
		p->last_system_time = system;
		p->last_irq_time = irq;
		p->last_soft_irq_time = softirq;
		p->last_io_wait_time = iowait;
		p->last_steal_time = steal;
		p->last_idle_time = idle;
		p->last_percentage_of_idle_time = 100.0;
		*idle_percentage = p->last_percentage_of_idle_time;
		return ZAP_SUCCESS;
	}

	usertime = (user - p->last_user_time) + (nice - p->last_nice_time);
	kerneltime = (system - p->last_system_time) + (irq - p->last_irq_time) + (softirq - p->last_soft_irq_time);
	kerneltime += (iowait - p->last_io_wait_time);
	kerneltime += (steal - p->last_steal_time);
	idletime = (idle - p->last_idle_time);

	totaltime = usertime + kerneltime + idletime;
	
	if (totaltime <= 0) {
		// this may happen if not enough time has elapsed and the jiffies counters are the same than the last time we checked
		// jiffies depend on timer interrupts which depend on the number of HZ compile time setting of the kernel
		// typical configs set HZ to 100 (that means, 100 jiffies updates per second, that is one each 10ms)
		// avoid an arithmetic exception and return the same values
		*idle_percentage = p->last_percentage_of_idle_time;
		return ZAP_SUCCESS;
	}

	halftime = totaltime / 2UL;

	p->last_percentage_of_idle_time = ((100 * idletime + halftime) / totaltime);
	*idle_percentage = p->last_percentage_of_idle_time;

	p->last_user_time = user;
	p->last_nice_time = nice;
	p->last_system_time = system;
	p->last_irq_time = irq;
	p->last_soft_irq_time = softirq;
	p->last_io_wait_time = iowait;
	p->last_steal_time = steal;
	p->last_idle_time = idle;

	return ZAP_SUCCESS;
}
Example #8
0
/**
 * \brief Process configuration variable for a Wanpipe profile
 * \param category Wanpipe profile name
 * \param var Variable name
 * \param val Variable value
 * \param lineno Line number from configuration file
 * \return Success
 */
static ZIO_CONFIGURE_FUNCTION(wanpipe_configure)
{
    int num;

    if (!strcasecmp(category, "defaults")) {
        if (!strcasecmp(var, "codec_ms")) {
            num = atoi(val);
            if (num < 10 || num > 60) {
                zap_log(ZAP_LOG_WARNING, "invalid codec ms at line %d\n", lineno);
            } else {
                wp_globals.codec_ms = num;
            }
        } else if (!strcasecmp(var, "wink_ms")) {
            num = atoi(val);
            if (num < 50 || num > 3000) {
                zap_log(ZAP_LOG_WARNING, "invalid wink ms at line %d\n", lineno);
            } else {
                wp_globals.wink_ms = num;
            }
        } else if (!strcasecmp(var, "flash_ms")) {
            num = atoi(val);
            if (num < 50 || num > 3000) {
                zap_log(ZAP_LOG_WARNING, "invalid flash ms at line %d\n", lineno);
            } else {
                wp_globals.flash_ms = num;
            }
        } else if (!strcasecmp(var, "ring_on_ms")) {
            num = atoi(val);
            if (num < 500 || num > 5000) {
                zap_log(ZAP_LOG_WARNING, "invalid ring_on_ms at line %d (valid range 500 to 5000)\n", lineno);
            } else {
                wp_globals.ring_on_ms = num;
            }
        } else if (!strcasecmp(var, "ring_off_ms")) {
            num = atoi(val);
            if (num < 500 || num > 5000) {
                zap_log(ZAP_LOG_WARNING, "invalid ring_off_ms at line %d (valid range 500 to 5000)\n", lineno);
            } else {
                wp_globals.ring_off_ms = num;
            }
        }
    }

    return ZAP_SUCCESS;
}
Example #9
0
int m3uac_connection_write(m3uac_connection_t *mcon, ss7bc_event_t *event)
{
	int err;

	if (!event || mcon->socket < 0 || !mcon->mutex) {
		zap_log(ZAP_LOG_DEBUG,  "Critical Error: No Event Device\n");
		return -EINVAL;
	}

	if (event->span > 16 || event->chan > 31) {
		zap_log(ZAP_LOG_CRIT, "Critical Error: TX Cmd=%s Invalid Span=%i Chan=%i\n", m3uac_event_id_name(event->event_id), event->span,event->chan);
		return -1;
	}

	gettimeofday(&event->tv,NULL);
	
	zap_mutex_lock(mcon->mutex);
	event->fseqno = mcon->txseq++;
	event->bseqno = mcon->rxseq;
	err = sendto(mcon->socket, event, sizeof(m3uac_event_t), 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
	zap_mutex_unlock(mcon->mutex);

	if (err != sizeof(m3uac_event_t)) {
		err = -1;
	}
	
 	zap_log(ZAP_LOG_DEBUG, "TX EVENT: %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i Cd=[%s] Ci=[%s]\n",
			m3uac_event_id_name(event->event_id),
			event->event_id,
			event->span+1,
			event->chan+1,
			event->release_cause,
			event->call_setup_id,
			event->fseqno,
			(event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"),
			(event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A")
			);

	return err;
}
Example #10
0
static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
{
	struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri);
	zap_size_t len = buflen -2;

	if (zap_channel_write(spri->dchan, buf, buflen, &len) != ZAP_SUCCESS) {
		zap_log(ZAP_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
		zap_clear_flag(spri, LPWRAP_PRI_READY);
		return -1;
	}

#ifdef IODEBUG
	{
		char bb[2048] = { 0 };

		print_hex_bytes(buf, buflen - 2, bb, sizeof(bb));
		zap_log(ZAP_LOG_DEBUG, "WRITE %d\n", (int)buflen-2);
	}
#endif

	return (int) buflen;
}
Example #11
0
m3uac_event_t *m3uac_connection_read(m3uac_connection_t *mcon, int iteration)
{
	unsigned int fromlen = sizeof(struct sockaddr_in);
	int bytes = 0;

	bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, 
					 (struct sockaddr *) &mcon->local_addr, &fromlen);

	if (bytes == sizeof(mcon->event) || bytes == (sizeof(mcon->event)-sizeof(uint32_t))) {

		if (mcon->rxseq_reset) {
			if (mcon->event.event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) {
				zap_log(ZAP_LOG_DEBUG, "Rx sync ok\n");
				mcon->rxseq = mcon->event.fseqno;
				return &mcon->event;
			}
			errno=EAGAIN;
			zap_log(ZAP_LOG_DEBUG, "Waiting for rx sync...\n");
			return NULL;
		}
		
		mcon->txwindow = mcon->txseq - mcon->event.bseqno;
		mcon->rxseq++;

		if (mcon->rxseq != mcon->event.fseqno) {
			zap_log(ZAP_LOG_CRIT, "Invalid Sequence Number Expect=%i Rx=%i\n", mcon->rxseq, mcon->event.fseqno);
			return NULL;
		}

		return &mcon->event;
	} else {
		if (iteration == 0) {
			zap_log(ZAP_LOG_CRIT, "Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
			return NULL;
		}
	}

	return NULL;
}
OZ_DECLARE(zap_status_t) _zap_mutex_lock(zap_mutex_t *mutex)
{
#ifdef WIN32
	EnterCriticalSection(&mutex->mutex);
#else
	int err;
	if ((err = pthread_mutex_lock(&mutex->mutex))) {
		zap_log(ZAP_LOG_ERROR, "Failed to lock mutex %d:%s\n", err, strerror(err));
		return ZAP_FAIL;
	}
#endif
	return ZAP_SUCCESS;
}
Example #13
0
static int create_conn_socket(m3uac_connection_t *mcon, char *local_ip, int local_port, char *ip, int port)
{
	int rc;
	struct hostent *result, *local_result;
	char buf[512], local_buf[512];
	int err = 0;

	memset(&mcon->remote_hp, 0, sizeof(mcon->remote_hp));
	memset(&mcon->local_hp, 0, sizeof(mcon->local_hp));
	mcon->socket = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
 
	zap_log(ZAP_LOG_DEBUG, "Creating L=%s:%d R=%s:%d\n",
			local_ip,local_port,ip,port);

	if (mcon->socket >= 0) {
		int flag;

		flag = 1;
		gethostbyname_r(ip, &mcon->remote_hp, buf, sizeof(buf), &result, &err);
		gethostbyname_r(local_ip, &mcon->local_hp, local_buf, sizeof(local_buf), &local_result, &err);
		if (result && local_result) {
			mcon->remote_addr.sin_family = mcon->remote_hp.h_addrtype;
			memcpy((char *) &mcon->remote_addr.sin_addr.s_addr, mcon->remote_hp.h_addr_list[0], mcon->remote_hp.h_length);
			mcon->remote_addr.sin_port = htons(port);

			mcon->local_addr.sin_family = mcon->local_hp.h_addrtype;
			memcpy((char *) &mcon->local_addr.sin_addr.s_addr, mcon->local_hp.h_addr_list[0], mcon->local_hp.h_length);
			mcon->local_addr.sin_port = htons(local_port);


			setsockopt(mcon->socket, IPPROTO_SCTP, SCTP_NODELAY, (char *)&flag, sizeof(int));

			rc=listen(mcon->socket,100);
			if (rc) {
			close(mcon->socket);
			mcon->socket = -1;
			
			}
		}
	}

	zap_mutex_create(&mcon->mutex);

	return mcon->socket;
}
Example #14
0
m3uac_event_t *m3uac_connection_readp(m3uac_connection_t *mcon, int iteration)
{
	unsigned int fromlen = sizeof(struct sockaddr_in);
	int bytes = 0;

	bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen);

	if (bytes == sizeof(mcon->event) || bytes == (sizeof(mcon->event)-sizeof(uint32_t))) {
		return &mcon->event;
	} else {
		if (iteration == 0) {
			zap_log(ZAP_LOG_CRIT, "Critical Error: PQ Invalid Event lenght from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
			return NULL;
		}
	}

	return NULL;
}
Example #15
0
int lpwrap_run_pri(struct lpwrap_pri *spri)
{
	int ret = 0;
	
	for (;;){
		ret = lpwrap_one_loop(spri);

		if (ret < 0) {

#ifndef WIN32 //This needs to be adressed fror WIN32 still
			if (errno == EINTR){
				/* Igonore an interrupted system call */
				continue;
			}
#endif	
			zap_log(ZAP_LOG_CRIT, "Error = %i [%s]\n", ret, strerror(errno));
			break;
		}
	}

	return ret;

}
Example #16
0
static ZIO_SIGNAL_CB_FUNCTION(on_signal)
{
	zap_log(ZAP_LOG_DEBUG, "got sig %d:%d [%s]\n", sigmsg->channel->span_id, sigmsg->channel->chan_id, zap_signal_event2str(sigmsg->event_id));

    switch(sigmsg->event_id) {

	case ZAP_SIGEVENT_STOP:
		THREADS[sigmsg->channel->span_id][sigmsg->channel->chan_id] = -1;
		break;

	case ZAP_SIGEVENT_START:
		if (!THREADS[sigmsg->channel->span_id][sigmsg->channel->chan_id]) {
			THREADS[sigmsg->channel->span_id][sigmsg->channel->chan_id] = 1;
			zap_thread_create_detached(channel_run, sigmsg->channel);
		}
		
		break;
	default:
		break;
	}
	
	return ZAP_SUCCESS;
}
Example #17
0
int lpwrap_one_loop(struct lpwrap_pri *spri)
{
	fd_set rfds, efds;
	struct timeval now = {0,0}, *next;
	pri_event *event;
	event_handler handler;
    int sel;
	
	if (spri->on_loop) {
		if ((sel = spri->on_loop(spri)) < 0) {
			return sel;
		}
	}

	if (spri->errs >= 2) {
		spri->errs = 0;
		return -1;
	}

	FD_ZERO(&rfds);
	FD_ZERO(&efds);

#ifdef _MSC_VER
	//Windows macro for FD_SET includes a warning C4127: conditional expression is constant
#pragma warning(push)
#pragma warning(disable:4127)
#endif

	FD_SET(pri_fd(spri->pri), &rfds);
	FD_SET(pri_fd(spri->pri), &efds);

#ifdef _MSC_VER
#pragma warning(pop)
#endif

	now.tv_sec = 0;
	now.tv_usec = 100000;

	sel = select(pri_fd(spri->pri) + 1, &rfds, NULL, &efds, &now);

	event = NULL;

	if (!sel) {
		if ((next = pri_schedule_next(spri->pri))) {
			gettimeofday(&now, NULL);
			if (now.tv_sec >= next->tv_sec && (now.tv_usec >= next->tv_usec || next->tv_usec <= 100000)) {
				//zap_log(ZAP_LOG_DEBUG, "Check event\n");
				event = pri_schedule_run(spri->pri);
			}
		}
	} else if (sel > 0) {
		event = pri_check_event(spri->pri);
	}

	if (event) {
		/* 0 is catchall event handler */
		if ((handler = spri->eventmap[event->e] ? spri->eventmap[event->e] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) {
			handler(spri, event->e, event);
		} else {
			zap_log(ZAP_LOG_CRIT, "No event handler found for event %d.\n", event->e);
		}
	}


	return sel;


	if ((handler = spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] ? spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) {
		handler(spri, LPWRAP_PRI_EVENT_IO_FAIL, NULL);
	}

	return -1;
}
Example #18
0
/**
 * \brief Executes an Openzap command on a Wanpipe channel
 * \param zchan Channel to execute command on
 * \param command Openzap command to execute
 * \param obj Object (unused)
 * \return Success or failure
 */
static ZIO_COMMAND_FUNCTION(wanpipe_command)
{
    wanpipe_tdm_api_t tdm_api;
    int err = 0;

    memset(&tdm_api, 0, sizeof(tdm_api));

    switch(command) {
    case ZAP_COMMAND_OFFHOOK:
    {
        err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "OFFHOOK Failed");
            return ZAP_FAIL;
        }
        zap_set_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK);
    }
    break;
    case ZAP_COMMAND_ONHOOK:
    {
        err=sangoma_tdm_txsig_onhook(zchan->sockfd,&tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "ONHOOK Failed");
            return ZAP_FAIL;
        }
        zap_clear_flag_locked(zchan, ZAP_CHANNEL_OFFHOOK);
    }
    break;
    case ZAP_COMMAND_GENERATE_RING_ON:
    {
        err=sangoma_tdm_txsig_start(zchan->sockfd,&tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring Failed");
            return ZAP_FAIL;
        }
        zap_set_flag_locked(zchan, ZAP_CHANNEL_RINGING);
        zap_set_pflag_locked(zchan, WP_RINGING);
        zchan->ring_time = zap_current_time_in_ms() + wp_globals.ring_on_ms;
    }
    break;
    case ZAP_COMMAND_GENERATE_RING_OFF:
    {
        err=sangoma_tdm_txsig_offhook(zchan->sockfd,&tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "Ring-off Failed");
            return ZAP_FAIL;
        }
        zap_clear_pflag_locked(zchan, WP_RINGING);
        zap_clear_flag_locked(zchan, ZAP_CHANNEL_RINGING);
    }
    break;
    case ZAP_COMMAND_GET_INTERVAL:
    {
        err=sangoma_tdm_get_usr_period(zchan->sockfd, &tdm_api);
        if (err > 0 ) {
            ZAP_COMMAND_OBJ_INT = err;
            err=0;
        }
    }
    break;
    case ZAP_COMMAND_ENABLE_ECHOCANCEL:
    {
        err=sangoma_tdm_enable_hwec(zchan->sockfd, &tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Enable Failed");
            return ZAP_FAIL;
        }
    }
    break;
    case ZAP_COMMAND_DISABLE_ECHOCANCEL:
    {
        err=sangoma_tdm_disable_hwec(zchan->sockfd, &tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "HWEC Disable Failed");
            return ZAP_FAIL;
        }
    }
    break;
    case ZAP_COMMAND_ENABLE_DTMF_DETECT:
    {
#ifdef WP_API_FEATURE_DTMF_EVENTS
        err = sangoma_tdm_enable_dtmf_events(zchan->sockfd, &tdm_api);
        if (err) {
            zap_log(ZAP_LOG_WARNING, "Enabling of Sangoma HW DTMF failed\n");
            snprintf(zchan->last_error, sizeof(zchan->last_error), "HW DTMF Enable Failed");
            return ZAP_FAIL;
        }
        zap_log(ZAP_LOG_DEBUG, "Enabled DTMF events on chan %d:%d\n", zchan->span_id, zchan->chan_id);
#else
        return ZAP_NOTIMPL;
#endif
    }
    break;
    case ZAP_COMMAND_DISABLE_DTMF_DETECT:
    {
#ifdef WP_API_FEATURE_DTMF_EVENTS
        err = sangoma_tdm_disable_dtmf_events(zchan->sockfd, &tdm_api);
        if (err) {
            zap_log(ZAP_LOG_WARNING, "Disabling of Sangoma HW DTMF failed\n");
            snprintf(zchan->last_error, sizeof(zchan->last_error), "HW DTMF Disable Failed");
            return ZAP_FAIL;
        }
        zap_log(ZAP_LOG_DEBUG, "Disabled DTMF events on chan %d:%d\n", zchan->span_id, zchan->chan_id);
#else
        return ZAP_NOTIMPL;
#endif
    }
    break;
    case ZAP_COMMAND_ENABLE_LOOP:
    {
#ifdef WP_API_FEATURE_LOOP
        err=sangoma_tdm_enable_loop(zchan->sockfd, &tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "Loop Enable Failed");
            return ZAP_FAIL;
        }
#endif
    }
    break;
    case ZAP_COMMAND_DISABLE_LOOP:
    {
#ifdef WP_API_FEATURE_LOOP
        err=sangoma_tdm_disable_loop(zchan->sockfd, &tdm_api);
        if (err) {
            snprintf(zchan->last_error, sizeof(zchan->last_error), "Loop Disable Failed");
            return ZAP_FAIL;
        }
#endif
    }
    break;
    case ZAP_COMMAND_SET_INTERVAL:
    {
        err=sangoma_tdm_set_usr_period(zchan->sockfd, &tdm_api, ZAP_COMMAND_OBJ_INT);
        zchan->packet_len = zchan->native_interval * (zchan->effective_codec == ZAP_CODEC_SLIN ? 16 : 8);
    }
    break;
    case ZAP_COMMAND_SET_CAS_BITS:
    {
#ifdef LIBSANGOMA_VERSION
        err = sangoma_tdm_write_rbs(zchan->sockfd,&tdm_api, zchan->physical_chan_id, wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT));
#else
        err = sangoma_tdm_write_rbs(zchan->sockfd, &tdm_api, wanpipe_swap_bits(ZAP_COMMAND_OBJ_INT));
#endif
    }
    break;
    case ZAP_COMMAND_GET_CAS_BITS:
    {
#ifdef LIBSANGOMA_VERSION
        unsigned char rbsbits;
        err = sangoma_tdm_read_rbs(zchan->sockfd, &tdm_api, zchan->physical_chan_id, &rbsbits);
        if (!err) {
            ZAP_COMMAND_OBJ_INT = wanpipe_swap_bits(rbsbits);
        }
#else
        // does sangoma_tdm_read_rbs is available here?
        ZAP_COMMAND_OBJ_INT = zchan->rx_cas_bits;
#endif
    }
    break;
    default:
        break;
    };

    if (err) {
        snprintf(zchan->last_error, sizeof(zchan->last_error), "%s", strerror(errno));
        return ZAP_FAIL;
    }


    return ZAP_SUCCESS;
}
Example #19
0
/**
 * \brief Initialises an openzap Wanpipe span from a configuration string
 * \param span Openzap span
 * \param str Configuration string
 * \param type Openzap span type
 * \param name Openzap span name
 * \param number Openzap span number
 * \return Success or failure
 */
static ZIO_CONFIGURE_SPAN_FUNCTION(wanpipe_configure_span)
{
    int items, i;
    char *mydata, *item_list[10];
    char *sp, *ch, *mx;
    unsigned char cas_bits = 0;
    int channo;
    int spanno;
    int top = 0;
    unsigned configured = 0;

    assert(str != NULL);


    mydata = strdup(str);
    assert(mydata != NULL);


    items = zap_separate_string(mydata, ',', item_list, (sizeof(item_list) / sizeof(item_list[0])));

    for(i = 0; i < items; i++) {
        sp = item_list[i];
        if ((ch = strchr(sp, ':'))) {
            *ch++ = '\0';
        }

        if (!(sp && ch)) {
            zap_log(ZAP_LOG_ERROR, "No valid wanpipe span and channel was specified\n");
            continue;
        }

        channo = atoi(ch);
        spanno = atoi(sp);

        if (channo < 0) {
            zap_log(ZAP_LOG_ERROR, "Invalid channel number %d\n", channo);
            continue;
        }

        if (spanno < 0) {
            zap_log(ZAP_LOG_ERROR, "Invalid span number %d\n", channo);
            continue;
        }

        if ((mx = strchr(ch, '-'))) {
            mx++;
            top = atoi(mx) + 1;
        } else {
            top = channo + 1;
        }


        if (top < 0) {
            zap_log(ZAP_LOG_ERROR, "Invalid range number %d\n", top);
            continue;
        }
        if (ZAP_CHAN_TYPE_CAS == type && zap_config_get_cas_bits(ch, &cas_bits)) {
            zap_log(ZAP_LOG_ERROR, "Failed to get CAS bits in CAS channel\n");
            continue;
        }
        configured += wp_open_range(span, spanno, channo, top, type, name, number, cas_bits);

    }

    free(mydata);

    return configured;
}
Example #20
0
/**
 * \brief Initialises a range of wanpipe channels
 * \param span Openzap span
 * \param spanno Wanpipe span number
 * \param start Initial wanpipe channel number
 * \param end Final wanpipe channel number
 * \param type Openzap channel type
 * \param name Openzap span name
 * \param number Openzap span number
 * \param cas_bits CAS bits
 * \return number of spans configured
 */
static unsigned wp_open_range(zap_span_t *span, unsigned spanno, unsigned start, unsigned end, zap_chan_type_t type, char *name, char *number, unsigned char cas_bits)
{
    unsigned configured = 0, x;
#ifdef LIBSANGOMA_VERSION
    sangoma_status_t sangstatus;
    sangoma_wait_obj_t *sangoma_wait_obj;
#endif

    if (type == ZAP_CHAN_TYPE_CAS) {
        zap_log(ZAP_LOG_DEBUG, "Configuring Wanpipe CAS channels with abcd == 0x%X\n", cas_bits);
    }
    for(x = start; x < end; x++) {
        zap_channel_t *chan;
        zap_socket_t sockfd = ZAP_INVALID_SOCKET;
        const char *dtmf = "none";
        if (!strncasecmp(span->name, "smg_prid_nfas", 8) && span->trunk_type == ZAP_TRUNK_T1 && x == 24) {
#ifdef LIBSANGOMA_VERSION
            sockfd = __tdmv_api_open_span_chan(spanno, x);
#else
            zap_log(ZAP_LOG_ERROR, "span %d channel %d cannot be configured as smg_prid_nfas, you need to compile openzap with newer libsangoma\n", spanno, x);
#endif
        } else {
            sockfd = tdmv_api_open_span_chan(spanno, x);
        }

        if (sockfd == ZAP_INVALID_SOCKET) {
            zap_log(ZAP_LOG_ERROR, "Failed to open wanpipe device span %d channel %d\n", spanno, x);
            continue;
        }

        if (zap_span_add_channel(span, sockfd, type, &chan) == ZAP_SUCCESS) {
            wanpipe_tdm_api_t tdm_api;
            memset(&tdm_api, 0, sizeof(tdm_api));
#ifdef LIBSANGOMA_VERSION
            sangstatus = sangoma_wait_obj_create(&sangoma_wait_obj, sockfd, SANGOMA_DEVICE_WAIT_OBJ);
            if (sangstatus != SANG_STATUS_SUCCESS) {
                zap_log(ZAP_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x);
                continue;
            }
            chan->mod_data = sangoma_wait_obj;
#endif

            chan->physical_span_id = spanno;
            chan->physical_chan_id = x;
            chan->rate = 8000;

            if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO || type == ZAP_CHAN_TYPE_B) {
                int err;

                dtmf = "software";

                /* FIXME: Handle Error Condition Check for return code */
                err = sangoma_tdm_get_hw_coding(chan->sockfd, &tdm_api);

                if (tdm_api.wp_tdm_cmd.hw_tdm_coding) {
                    chan->native_codec = chan->effective_codec = ZAP_CODEC_ALAW;
                } else {
                    chan->native_codec = chan->effective_codec = ZAP_CODEC_ULAW;
                }

                err = sangoma_tdm_get_hw_dtmf(chan->sockfd, &tdm_api);
                if (err > 0) {
                    err = sangoma_tdm_enable_dtmf_events(chan->sockfd, &tdm_api);
                    if (err == 0) {
                        zap_channel_set_feature(chan, ZAP_CHANNEL_FEATURE_DTMF_DETECT);
                        dtmf = "hardware";
                    }
                }
            }

#ifdef LIBSANGOMA_VERSION
            if (type == ZAP_CHAN_TYPE_FXS) {
                if (sangoma_tdm_disable_ring_trip_detect_events(chan->sockfd, &tdm_api)) {
                    /* we had problems of on-hook/off-hook detection due to how ring trip events were handled
                     * if this fails, I believe we will still work ok as long as we dont handle them incorrectly */
                    zap_log(ZAP_LOG_WARNING, "Failed to disable ring trip events in channel s%dc%d\n", spanno, x);
                }
            }
#endif
#if 0
            if (type == ZAP_CHAN_TYPE_FXS || type == ZAP_CHAN_TYPE_FXO) {
                /* Enable FLASH/Wink Events */
                int err=sangoma_set_rm_rxflashtime(chan->sockfd, &tdm_api, wp_globals.flash_ms);
                if (err == 0) {
                    zap_log(ZAP_LOG_ERROR, "flash enabled s%dc%d\n", spanno, x);
                } else {
                    zap_log(ZAP_LOG_ERROR, "flash disabled s%dc%d\n", spanno, x);
                }
            }
#endif

            if (type == ZAP_CHAN_TYPE_CAS || type == ZAP_CHAN_TYPE_EM) {
#ifdef LIBSANGOMA_VERSION
                sangoma_tdm_write_rbs(chan->sockfd,&tdm_api,chan->physical_chan_id, wanpipe_swap_bits(cas_bits));

                /* this should probably be done for old libsangoma but I am not sure if the API is available and I'm lazy to check,
                   The poll rate is hard coded to 100 per second (done in the driver, is the max rate of polling allowed by wanpipe)
                 */
                if (sangoma_tdm_enable_rbs_events(chan->sockfd, &tdm_api, 100)) {
                    zap_log(ZAP_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd);
                    continue;
                }
                /* probably done by the driver but lets write defensive code this time */
                sangoma_flush_bufs(chan->sockfd, &tdm_api);
#else
                /*
                 * With wanpipe 3.4.4.2 I get failure even though the events are enabled, /var/log/messages said:
                 * wanpipe4: WARNING: Event type 9 is already pending!
                 * wanpipe4: Failed to add new fe event 09 ch_map=FFFFFFFF!
                 * may be we should not send an error until that is fixed in the driver
                 */
                if (sangoma_tdm_enable_rbs_events(chan->sockfd, &tdm_api, 100)) {
                    zap_log(ZAP_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd);
                }
                /* probably done by the driver but lets write defensive code this time */
                sangoma_tdm_flush_bufs(chan->sockfd, &tdm_api);
                sangoma_tdm_write_rbs(chan->sockfd,&tdm_api, wanpipe_swap_bits(cas_bits));
#endif
            }

            if (!zap_strlen_zero(name)) {
                zap_copy_string(chan->chan_name, name, sizeof(chan->chan_name));
            }

            if (!zap_strlen_zero(number)) {
                zap_copy_string(chan->chan_number, number, sizeof(chan->chan_number));
            }
            configured++;
            zap_log(ZAP_LOG_INFO, "configuring device s%dc%d as OpenZAP device %d:%d fd:%d DTMF: %s\n",
                    spanno, x, chan->span_id, chan->chan_id, sockfd, dtmf);

        } else {
            zap_log(ZAP_LOG_ERROR, "zap_span_add_channel failed for wanpipe span %d channel %d\n", spanno, x);
        }
    }

    return configured;
}
OZ_DECLARE(zap_status_t) zap_interrupt_wait(zap_interrupt_t *interrupt, int ms)
{
	int num = 1;
#ifdef WIN32
	DWORD res = 0;
	HANDLE ints[2];
#else
	int res = 0;
	struct pollfd ints[2];
	char pipebuf[255];
#endif

	/* start implementation */
#ifdef WIN32
	ints[0] = interrupt->event;
	if (interrupt->device != ZAP_INVALID_SOCKET) {
		num++;
		ints[1] = interrupt->device;
	}
	res = WaitForMultipleObjects(num, ints, FALSE, ms >= 0 ? ms : INFINITE);
	switch (res) {
	case WAIT_TIMEOUT:
		return ZAP_TIMEOUT;
	case WAIT_FAILED:
	case WAIT_ABANDONED: /* is it right to fail with abandoned? */
		return ZAP_FAIL;
	default:
		if (res >= (sizeof(ints)/sizeof(ints[0]))) {
			zap_log(ZAP_LOG_ERROR, "Error waiting for openzap interrupt event (WaitForSingleObject returned %d)\n", res);
			return ZAP_FAIL;
		}
		return ZAP_SUCCESS;
	}
#else
	ints[0].fd = interrupt->readfd;
	ints[0].events = POLLIN;
	ints[0].revents = 0;

	if (interrupt->device != ZAP_INVALID_SOCKET) {
		num++;
		ints[1].fd = interrupt->device;
		ints[1].events = POLLIN;
		ints[1].revents = 0;
	}

	res = poll(ints, num, ms);
	if (res == -1) {
		zap_log(ZAP_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno));
		return ZAP_FAIL;
	}

	if (res == 0) {
		return ZAP_TIMEOUT;
	}

	if (ints[0].revents & POLLIN) {
		res = read(ints[0].fd, pipebuf, sizeof(pipebuf));
		if (res == -1) {
			zap_log(ZAP_LOG_CRIT, "reading interrupt descriptor failed (%s)\n", strerror(errno));
		}
	}

	return ZAP_SUCCESS;
#endif
}