root/src/ftmod/ftmod_libpri/lpwrap_pri.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gettimeofday
  2. lpwrap_pri_event_str
  3. __pri_lpwrap_read
  4. __pri_lpwrap_write
  5. lpwrap_init_pri
  6. lpwrap_one_loop
  7. lpwrap_run_pri

   1 /*
   2  * Copyright (c) 2009, Anthony Minessale II
   3  * All rights reserved.
   4  * 
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 
   9  * * Redistributions of source code must retain the above copyright
  10  * notice, this list of conditions and the following disclaimer.
  11  * 
  12  * * Redistributions in binary form must reproduce the above copyright
  13  * notice, this list of conditions and the following disclaimer in the
  14  * documentation and/or other materials provided with the distribution.
  15  * 
  16  * * Neither the name of the original author; nor the names of any contributors
  17  * may be used to endorse or promote products derived from this software
  18  * without specific prior written permission.
  19  * 
  20  * 
  21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  25  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 
  34 //#define IODEBUG
  35 
  36 #include "private/ftdm_core.h"
  37 #include "lpwrap_pri.h"
  38 #ifndef HAVE_GETTIMEOFDAY
  39 
  40 #ifdef WIN32
  41 #include <mmsystem.h>
  42 
  43 static __inline int gettimeofday(struct timeval *tp, void *nothing)
  44 {
  45 #ifdef WITHOUT_MM_LIB
  46         SYSTEMTIME st;
  47         time_t tt;
  48         struct tm tmtm;
  49         /* mktime converts local to UTC */
  50         GetLocalTime (&st);
  51         tmtm.tm_sec = st.wSecond;
  52         tmtm.tm_min = st.wMinute;
  53         tmtm.tm_hour = st.wHour;
  54         tmtm.tm_mday = st.wDay;
  55         tmtm.tm_mon = st.wMonth - 1;
  56         tmtm.tm_year = st.wYear - 1900;  tmtm.tm_isdst = -1;
  57         tt = mktime (&tmtm);
  58         tp->tv_sec = tt;
  59         tp->tv_usec = st.wMilliseconds * 1000;
  60 #else
  61         /**
  62          ** The earlier time calculations using GetLocalTime
  63          ** had a time resolution of 10ms.The timeGetTime, part
  64          ** of multimedia apis offer a better time resolution
  65          ** of 1ms.Need to link against winmm.lib for this
  66          **/
  67         unsigned long Ticks = 0;
  68         unsigned long Sec =0;
  69         unsigned long Usec = 0;
  70         Ticks = timeGetTime();
  71 
  72         Sec = Ticks/1000;
  73         Usec = (Ticks - (Sec*1000))*1000;
  74         tp->tv_sec = Sec;
  75         tp->tv_usec = Usec;
  76 #endif /* WITHOUT_MM_LIB */
  77         (void)nothing;
  78         return 0;
  79 }
  80 #endif /* WIN32 */
  81 #endif /* HAVE_GETTIMEOFDAY */
  82 
  83 static struct lpwrap_pri_event_list LPWRAP_PRI_EVENT_LIST[] = {
  84         {0, LPWRAP_PRI_EVENT_ANY, "ANY"},
  85         {1, LPWRAP_PRI_EVENT_DCHAN_UP, "DCHAN_UP"},
  86         {2, LPWRAP_PRI_EVENT_DCHAN_DOWN, "DCHAN_DOWN"},
  87         {3, LPWRAP_PRI_EVENT_RESTART, "RESTART"},
  88         {4, LPWRAP_PRI_EVENT_CONFIG_ERR, "CONFIG_ERR"},
  89         {5, LPWRAP_PRI_EVENT_RING, "RING"},
  90         {6, LPWRAP_PRI_EVENT_HANGUP, "HANGUP"},
  91         {7, LPWRAP_PRI_EVENT_RINGING, "RINGING"},
  92         {8, LPWRAP_PRI_EVENT_ANSWER, "ANSWER"},
  93         {9, LPWRAP_PRI_EVENT_HANGUP_ACK, "HANGUP_ACK"},
  94         {10, LPWRAP_PRI_EVENT_RESTART_ACK, "RESTART_ACK"},
  95         {11, LPWRAP_PRI_EVENT_FACNAME, "FACNAME"},
  96         {12, LPWRAP_PRI_EVENT_INFO_RECEIVED, "INFO_RECEIVED"},
  97         {13, LPWRAP_PRI_EVENT_PROCEEDING, "PROCEEDING"},
  98         {14, LPWRAP_PRI_EVENT_SETUP_ACK, "SETUP_ACK"},
  99         {15, LPWRAP_PRI_EVENT_HANGUP_REQ, "HANGUP_REQ"},
 100         {16, LPWRAP_PRI_EVENT_NOTIFY, "NOTIFY"},
 101         {17, LPWRAP_PRI_EVENT_PROGRESS, "PROGRESS"},
 102         {18, LPWRAP_PRI_EVENT_KEYPAD_DIGIT, "KEYPAD_DIGIT"},
 103         {19, LPWRAP_PRI_EVENT_IO_FAIL, "IO_FAIL"},
 104 };
 105 
 106 #define LINE "--------------------------------------------------------------------------------"
 107 
 108 const char *lpwrap_pri_event_str(lpwrap_pri_event_t event_id)
 109 { 
 110         return LPWRAP_PRI_EVENT_LIST[event_id].name;
 111 }
 112 
 113 static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
 114 {
 115         struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri);
 116         ftdm_size_t len = buflen;
 117         int res;
 118         ftdm_status_t zst;
 119 
 120         if ((zst = ftdm_channel_read(spri->dchan, buf, &len)) != FTDM_SUCCESS) {
 121                 if (zst == FTDM_FAIL) {
 122                         ftdm_log(FTDM_LOG_CRIT, "span %d D-READ FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
 123                         spri->errs++;
 124                 } else {
 125                         ftdm_log(FTDM_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id);
 126                 }
 127                 
 128                 ftdm_clear_flag(spri, LPWRAP_PRI_READY);
 129                 return -1;
 130         }
 131         spri->errs = 0;
 132         res = (int)len;
 133         memset(&((unsigned char*)buf)[res],0,2);
 134         res+=2;
 135 
 136 #ifdef IODEBUG
 137         {
 138                 char bb[2048] = { 0 };
 139 
 140                 print_hex_bytes(buf, res - 2, bb, sizeof(bb));
 141                 ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res-2);
 142         }
 143 #endif
 144 
 145         return res;
 146 }
 147 
 148 static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
 149 {
 150         struct lpwrap_pri *spri = (struct lpwrap_pri *) pri_get_userdata(pri);
 151         ftdm_size_t len = buflen -2;
 152 
 153         if (ftdm_channel_write(spri->dchan, buf, buflen, &len) != FTDM_SUCCESS) {
 154                 ftdm_log(FTDM_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
 155                 ftdm_clear_flag(spri, LPWRAP_PRI_READY);
 156                 return -1;
 157         }
 158 
 159 #ifdef IODEBUG
 160         {
 161                 char bb[2048] = { 0 };
 162 
 163                 print_hex_bytes(buf, buflen - 2, bb, sizeof(bb));
 164                 ftdm_log(FTDM_LOG_DEBUG, "WRITE %d\n", (int)buflen-2);
 165         }
 166 #endif
 167 
 168         return (int) buflen;
 169 }
 170 
 171 int lpwrap_init_pri(struct lpwrap_pri *spri, ftdm_span_t *span, ftdm_channel_t *dchan, int swtype, int node, int debug)
 172 {
 173         int ret = -1;
 174 
 175         memset(spri, 0, sizeof(struct lpwrap_pri));
 176         
 177         spri->dchan = dchan;
 178         spri->span = span;
 179 
 180         if (spri->dchan && (spri->pri = pri_new_cb(spri->dchan->sockfd, node, swtype, __pri_lpwrap_read, __pri_lpwrap_write, spri))){
 181                 unsigned char buf[4] = { 0 };
 182                 size_t buflen = sizeof(buf), len = 0;
 183                 pri_set_debug(spri->pri, debug);
 184                 ret = 0;
 185                 
 186                 ftdm_channel_write(spri->dchan, buf, buflen, &len);
 187         } else {
 188                 fprintf(stderr, "Unable to create PRI\n");
 189         }
 190 
 191         return ret;
 192 }
 193 
 194 
 195 int lpwrap_one_loop(struct lpwrap_pri *spri)
 196 {
 197         fd_set rfds, efds;
 198         struct timeval now = {0,0}, *next;
 199         pri_event *event;
 200         event_handler handler;
 201     int sel;
 202         
 203         if (spri->on_loop) {
 204                 if ((sel = spri->on_loop(spri)) < 0) {
 205                         return sel;
 206                 }
 207         }
 208 
 209         if (spri->errs >= 2) {
 210                 spri->errs = 0;
 211                 return -1;
 212         }
 213 
 214         FD_ZERO(&rfds);
 215         FD_ZERO(&efds);
 216 
 217 #ifdef _MSC_VER
 218         //Windows macro for FD_SET includes a warning C4127: conditional expression is constant
 219 #pragma warning(push)
 220 #pragma warning(disable:4127)
 221 #endif
 222 
 223         FD_SET(pri_fd(spri->pri), &rfds);
 224         FD_SET(pri_fd(spri->pri), &efds);
 225 
 226 #ifdef _MSC_VER
 227 #pragma warning(pop)
 228 #endif
 229 
 230         now.tv_sec = 0;
 231         now.tv_usec = 100000;
 232 
 233         sel = select(pri_fd(spri->pri) + 1, &rfds, NULL, &efds, &now);
 234 
 235         event = NULL;
 236 
 237         if (!sel) {
 238                 if ((next = pri_schedule_next(spri->pri))) {
 239                         gettimeofday(&now, NULL);
 240                         if (now.tv_sec >= next->tv_sec && (now.tv_usec >= next->tv_usec || next->tv_usec <= 100000)) {
 241                                 //ftdm_log(FTDM_LOG_DEBUG, "Check event\n");
 242                                 event = pri_schedule_run(spri->pri);
 243                         }
 244                 }
 245         } else if (sel > 0) {
 246                 event = pri_check_event(spri->pri);
 247         }
 248 
 249         if (event) {
 250                 /* 0 is catchall event handler */
 251                 if ((handler = spri->eventmap[event->e] ? spri->eventmap[event->e] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) {
 252                         handler(spri, event->e, event);
 253                 } else {
 254                         ftdm_log(FTDM_LOG_CRIT, "No event handler found for event %d.\n", event->e);
 255                 }
 256         }
 257 
 258 
 259         return sel;
 260 
 261 
 262         if ((handler = spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] ? spri->eventmap[LPWRAP_PRI_EVENT_IO_FAIL] : spri->eventmap[0] ? spri->eventmap[0] : NULL)) {
 263                 handler(spri, LPWRAP_PRI_EVENT_IO_FAIL, NULL);
 264         }
 265 
 266         return -1;
 267 }
 268 
 269 int lpwrap_run_pri(struct lpwrap_pri *spri)
 270 {
 271         int ret = 0;
 272         
 273         for (;;){
 274                 ret = lpwrap_one_loop(spri);
 275 
 276                 if (ret < 0) {
 277 
 278 #ifndef WIN32 //This needs to be adressed fror WIN32 still
 279                         if (errno == EINTR){
 280                                 /* Igonore an interrupted system call */
 281                                 continue;
 282                         }
 283 #endif  
 284                         ftdm_log(FTDM_LOG_CRIT, "Error = %i [%s]\n", ret, strerror(errno));
 285                         break;
 286                 }
 287         }
 288 
 289         return ret;
 290 
 291 }
 292 
 293 /* For Emacs:
 294  * Local Variables:
 295  * mode:c
 296  * indent-tabs-mode:t
 297  * tab-width:4
 298  * c-basic-offset:4
 299  * End:
 300  * For VIM:
 301  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
 302  */
 303 

/* [<][>][^][v][top][bottom][index][help] */