static int __pri_sangoma_read(struct pri *pri, void *buf, int buflen) { unsigned char tmpbuf[sizeof(wp_tdm_api_rx_hdr_t)]; int prifd = pri_fd(pri); /* NOTE: This code will be different for A104 * A104 receives data + 2byte CRC + 1 byte flag * A101/2 receives data only */ int res = sangoma_readmsg_socket(prifd, tmpbuf, sizeof(wp_tdm_api_rx_hdr_t), buf, buflen, 0); if (res > 0){ #ifdef WANPIPE_LEGACY_A104 /* Prior 2.3.4 release A104 API passed up * 3 extra bytes: 2 CRC + 1 FLAG, * PRI is expecting only 2 CRC bytes, thus we * must remove 1 flag byte */ res--; #else /* Add 2 byte CRC and set it to ZERO */ memset(&((unsigned char*)buf)[res],0,2); res+=2; #endif } else if (res < 0) { sbridge_log(SBRIDGE_LOG_ERROR, "Failed to read PRI from sangoma device %d: %s\n", prifd, sbridge_os_get_last_error()); } return res; }
static int __pri_sangoma_write(struct pri *pri, void *buf, int buflen) { unsigned char tmpbuf[sizeof(wp_tdm_api_rx_hdr_t)]; int res, myerrno; int prifd = pri_fd(pri); memset(&tmpbuf[0],0,sizeof(wp_tdm_api_rx_hdr_t)); if (buflen < 1){ /* HDLC Frame must be greater than 2byte CRC */ sbridge_log(SBRIDGE_LOG_ERROR, "Got short PRI frame of len %d\n", buflen); return -1; } /* FIXME: This might cause problems with other libraries * We must remove 2 bytes from buflen because * libpri sends 2 fake CRC bytes */ res = sangoma_sendmsg_socket(prifd, tmpbuf, sizeof(wp_tdm_api_rx_hdr_t), buf, (unsigned short)buflen - 2, 0); if (res > 0){ res = buflen; } else if (res < 0) { myerrno = errno; sbridge_log(SBRIDGE_LOG_ERROR, "Failed to write %d bytes to PRI sangoma device %d: %s\n", buflen, prifd, sbridge_os_get_last_error()); if (errno == EBUSY) { /* TODO: flush buffers */ } } return res; }
static void *dchan(void *data) { /* Joint D-channel */ struct pri *pri = data; struct timeval *next, tv; pri_event *e; fd_set fds; int res; for(;;) { if ((next = pri_schedule_next(pri))) { gettimeofday(&tv, NULL); tv.tv_sec = next->tv_sec - tv.tv_sec; tv.tv_usec = next->tv_usec - tv.tv_usec; if (tv.tv_usec < 0) { tv.tv_usec += 1000000; tv.tv_sec -= 1; } if (tv.tv_sec < 0) { tv.tv_sec = 0; tv.tv_usec = 0; } } FD_ZERO(&fds); FD_SET(pri_fd(pri), &fds); res = select(pri_fd(pri) + 1, &fds, NULL, NULL, next ? &tv : NULL); pthread_mutex_lock(&lock); cur = pri; if (res < 0) { perror("select"); } else if (!res) { e = pri_schedule_run(pri); } else { e = pri_check_event(pri); } if (e) { if (first == pri) { event1(pri, e); } else { event2(pri, e); } } pthread_mutex_unlock(&lock); } return NULL; }
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; }
int sangoma_one_loop(struct sangoma_pri *spri) { fd_set rfds; // we dont need efds unless we want to handle span alarms // right now sbridge does not makes calls, so there is no point // in handling alarms //fd_set efds; struct timeval now = {0,0}, *next; pri_event *event; int sel; sbridge_mutex_lock(&spri->lock); if (spri->on_loop) { spri->on_loop(spri); } 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 if ((next = pri_schedule_next(spri->pri))) { gettimeofday(&now, NULL); now.tv_sec = next->tv_sec - now.tv_sec; now.tv_usec = next->tv_usec - now.tv_usec; if (now.tv_usec < 0) { now.tv_usec += 1000000; now.tv_sec -= 1; } if (now.tv_sec < 0) { now.tv_sec = 0; now.tv_usec = 0; } } sbridge_mutex_unlock(&spri->lock); //sel = select(pri_fd(spri->pri) + 1, &rfds, NULL, &efds, next ? &now : NULL); sel = select(pri_fd(spri->pri) + 1, &rfds, NULL, NULL, next ? &now : NULL); sbridge_mutex_lock(&spri->lock); event = NULL; if (!sel) { event = pri_schedule_run(spri->pri); } else if (sel > 0) { event = pri_check_event(spri->pri); } else if (errno != EINTR){ sbridge_log(SBRIDGE_LOG_ERROR, "select failed: %s\n", sbridge_os_get_last_error()); } else { /* at this point we know there is a select error and is EINTR, ignore */ sel = 0; } if (event) { event_handler handler; /* 0 is catchall event handler */ const int eventmap_size = sizeof(spri->eventmap)/sizeof(spri->eventmap[0]); if (eventmap_size <= event->e) { sbridge_log(SBRIDGE_LOG_ERROR, "Event %d is too big, we did not expect it!.\n", event->e); } else { if ((handler = spri->eventmap[event->e] ? spri->eventmap[event->e] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) { handler(spri, event->e, event); } else { sbridge_log(SBRIDGE_LOG_ERROR, "No event handler found for event %d.\n", event->e); } } } sbridge_mutex_unlock(&spri->lock); return sel; }
int sangoma_close_pri(struct sangoma_pri *spri) { int prifd = pri_fd(spri->pri); sangoma_socket_close(&prifd); return 0; }