Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 54176) +++ channels/chan_sip.c (working copy) @@ -143,6 +143,13 @@ #include "asterisk/translate.h" #include "asterisk/version.h" +#ifdef WITH_SMDI +#include "asterisk/smdi.h" +#include "asterisk/astobj.h" +#define SMDI_MD_WAIT_TIMEOUT 1500 +#define DEFAULT_SMDI_PORT "/dev/ttyS0" +#endif + #ifndef FALSE #define FALSE 0 #endif @@ -587,6 +594,12 @@ static int apeerobjs = 0; /*!< Autocreated peer objects */ static int regobjs = 0; /*!< Registry objects */ +#ifdef WITH_SMDI +static int global_use_smdi = 0; +static char global_smdi_port[SMDI_MAX_FILENAME_LEN]; +static int global_smdipairing = 0; /*!< Turn INVITE/SMDI pairing on/off */ +#endif + static struct ast_flags global_flags[2] = {{0}}; /*!< global SIP_ flags */ AST_MUTEX_DEFINE_STATIC(netlock); @@ -989,6 +1002,11 @@ char lastmsg[256]; /*!< Last Message sent/received */ int amaflags; /*!< AMA Flags */ int pendinginvite; /*!< Any pending invite ? (seqno of this) */ +#ifdef WITH_SMDI + unsigned int use_smdi; /*!< Use SMDI checking */ + struct ast_smdi_interface *smdi_iface; /*!< SMDI serial port */ +#endif + struct sip_request initreq; /*!< Latest request that opened a new transaction within this dialog. NOT the request that opened the dialog @@ -4413,6 +4431,9 @@ p->initid = -1; p->autokillid = -1; p->subscribed = NONE; +#ifdef WITH_SMDI + p->use_smdi = global_use_smdi; +#endif p->stateid = -1; p->prefs = default_prefs; /* Set default codecs for this call */ @@ -4508,6 +4529,17 @@ } ast_string_field_set(p, context, default_context); +#ifdef WITH_SMDI + /* set up SMDI info */ + if (p->use_smdi) { + p->smdi_iface = ast_smdi_interface_find(global_smdi_port); + if (!(p->smdi_iface)) { + ast_log(LOG_ERROR, "Invalid SMDI port specfied, disabling SMDI support\n"); + p->use_smdi = 0; + } + } +#endif + /* Add to active dialog list */ dialoglist_lock(); p->next = dialoglist; @@ -13435,7 +13467,11 @@ const char *required; unsigned int required_profile = 0; struct ast_channel *c = NULL; /* New channel */ +#ifdef WITH_SMDI + struct ast_smdi_md_message *smdi_msg = NULL; +#endif + /* Find out what they support */ if (!p->sipoptions) { const char *supported = get_header(req, "Supported"); @@ -13753,6 +13789,56 @@ if (c) { /* We have a call -either a new call or an old one (RE-INVITE) */ + +#ifdef WITH_SMDI + /* check for SMDI messages */ + if (p->use_smdi && p->smdi_iface) { + /* get context */ + if (option_debug > 2) + ast_log(LOG_DEBUG, "SMDI: looking for new SMDI message with line: %s...\n",p->exten); + if (global_smdipairing) { + smdi_msg = ast_smdi_md_message_wait_for_callid(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT, (char *)p->exten); + } else { + smdi_msg = ast_smdi_md_message_wait(p->smdi_iface, SMDI_MD_WAIT_TIMEOUT); + } + if (smdi_msg != NULL) { + if (option_debug > 2) { + ast_log(LOG_DEBUG, "Received SMDI message on %s\n", c->name); + ast_log(LOG_DEBUG, "copying exten %s\n", smdi_msg->fwd_st); + } + ast_copy_string((char *)p->exten, smdi_msg->fwd_st, sizeof(p->exten)); + pbx_builtin_setvar_helper(c, "_SMDI_EXTEN", smdi_msg->fwd_st); + if (option_debug > 2) + ast_log(LOG_DEBUG, "copying CID %s\n", smdi_msg->calling_st); + pbx_builtin_setvar_helper(c, "_SMDI_CID", smdi_msg->calling_st); + ast_copy_string(p->owner->cid.cid_num, smdi_msg->calling_st, sizeof(smdi_msg->calling_st)); /* ast_copy_string(p->owner->cid.cid_num, smdi_msg->calling_st, sizeof(p->owner->cid.cid_num)); */ + if (option_debug > 2) + ast_log(LOG_DEBUG, "checking type %c\n", smdi_msg->type); + if (smdi_msg->type == 'B') { + if (option_debug > 2) { + ast_log(LOG_DEBUG, "checking type %c\n", smdi_msg->type); + ast_log(LOG_DEBUG, "type B...\n"); + } + pbx_builtin_setvar_helper(c, "_SMDI_VM_TYPE", "b"); + } else if (smdi_msg->type == 'N') { + if (option_debug > 2) + ast_log(LOG_DEBUG, "type N...\n"); + pbx_builtin_setvar_helper(c, "_SMDI_VM_TYPE", "u"); + } else if (smdi_msg->type == 'A') { + if (option_debug > 2) + ast_log(LOG_DEBUG, "type A...\n"); + pbx_builtin_setvar_helper(c, "_SMDI_VM_TYPE", "u"); + } else if (smdi_msg->type == 'U') { + if (option_debug > 2) + ast_log(LOG_DEBUG, "type U...\n"); + pbx_builtin_setvar_helper(c, "_SMDI_VM_TYPE", "u"); + } + } else { + ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n"); + } + } +#endif + switch(c->_state) { case AST_STATE_DOWN: if (option_debug > 1) @@ -16494,6 +16580,9 @@ /* Initialize some reasonable defaults at SIP reload (used both for channel and as default for peers and users */ ast_copy_string(default_context, DEFAULT_CONTEXT, sizeof(default_context)); +#ifdef WITH_SMDI + ast_copy_string(global_smdi_port, DEFAULT_SMDI_PORT, sizeof(global_smdi_port)); +#endif default_subscribecontext[0] = '\0'; default_language[0] = '\0'; default_fromdomain[0] = '\0'; @@ -16548,6 +16637,14 @@ ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTSAVE_SYSNAME); } else if (!strcasecmp(v->name, "rtupdate")) { ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTUPDATE); +#ifdef WITH_SMDI + } else if (!strcasecmp(v->name, "usesmdi")) { + global_use_smdi = ast_true(v->value); + } else if (!strcasecmp(v->name, "smdiport")) { + ast_copy_string(global_smdi_port, v->value, sizeof(global_smdi_port)); + } else if (!strcasecmp(v->name, "smdipairing")) { + global_smdipairing = ast_true(v->value); +#endif } else if (!strcasecmp(v->name, "ignoreregexpire")) { ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_IGNOREREGEXPIRE); } else if (!strcasecmp(v->name, "t1min")) { Index: channels/Makefile =================================================================== --- channels/Makefile (revision 54176) +++ channels/Makefile (working copy) @@ -109,8 +109,10 @@ chan_misdn.o: ASTCFLAGS+=-Imisdn -misdn_config.o: ASTCFLAGS+=-Imisdn +chan_sip.o: ASTCFLAGS+=-DWITH_SMDI=1 +misdn_config.o: ASTCFLAGS+=-Imisdn + misdn/isdn_lib.o: ASTCFLAGS+=-Wno-strict-aliasing $(if $(filter chan_misdn,$(EMBEDDED_MODS)),modules.link,chan_misdn.so): chan_misdn.o misdn_config.o misdn/isdn_lib.o misdn/isdn_msg_parser.o Index: apps/app_voicemail.c =================================================================== --- apps/app_voicemail.c (revision 54176) +++ apps/app_voicemail.c (working copy) @@ -304,6 +304,7 @@ char pager[80]; /*!< E-mail address to pager (no attachment) */ char serveremail[80]; /*!< From: Mail address */ char mailcmd[160]; /*!< Configurable mail command */ + char usesmdi[4]; /*!< notify via SMDI */ char language[MAX_LANGUAGE]; /*!< Config: Language setting */ char zonetag[80]; /*!< Time zone */ char callback[80]; @@ -584,6 +585,8 @@ ast_copy_string(vmu->language, value, sizeof(vmu->language)); } else if (!strcasecmp(var, "tz")) { ast_copy_string(vmu->zonetag, value, sizeof(vmu->zonetag)); + } else if (!strcasecmp(var, "usesmdi")) { + ast_copy_string(vmu->usesmdi, value, sizeof(vmu->zonetag)); #ifdef IMAP_STORAGE } else if (!strcasecmp(var, "imapuser")) { ast_copy_string(vmu->imapuser, value, sizeof(vmu->imapuser)); @@ -2778,7 +2781,7 @@ #endif -static void run_externnotify(char *context, char *extension) +static void run_externnotify(char *context, char *extension, char *usesmdi) { char arguments[255]; char ext_context[256] = ""; @@ -2790,7 +2793,7 @@ else ast_copy_string(ext_context, extension, sizeof(ext_context)); - if (!strcasecmp(externnotify, "smdi")) { + if (!strcasecmp(externnotify, "smdi") || ast_true(usesmdi)) { if (ast_app_has_voicemail(ext_context, NULL)) ast_smdi_mwi_set(smdi_iface, extension); else @@ -3946,7 +3949,7 @@ ast_app_inboxcount(ext_context, &newmsgs, &oldmsgs); } manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s@%s\r\nWaiting: %d\r\nNew: %d\r\nOld: %d\r\n", vmu->mailbox, vmu->context, ast_app_has_voicemail(ext_context, NULL), newmsgs, oldmsgs); - run_externnotify(vmu->context, vmu->mailbox); + run_externnotify(vmu->context, vmu->mailbox, vmu->usesmdi); return 0; } @@ -6713,7 +6716,7 @@ if (valid) { snprintf(ext_context, sizeof(ext_context), "%s@%s", vms.username, vmu->context); manager_event(EVENT_FLAG_CALL, "MessageWaiting", "Mailbox: %s\r\nWaiting: %d\r\n", ext_context, has_voicemail(ext_context, NULL)); - run_externnotify(vmu->context, vmu->mailbox); + run_externnotify(vmu->context, vmu->mailbox, vmu->usesmdi); } #ifdef IMAP_STORAGE /* expunge message - use UID Expunge if supported on IMAP server*/ Index: include/asterisk/smdi.h =================================================================== --- include/asterisk/smdi.h (revision 54176) +++ include/asterisk/smdi.h (working copy) @@ -106,6 +106,7 @@ /* MD message queue functions */ struct ast_smdi_md_message *ast_smdi_md_message_pop(struct ast_smdi_interface *iface); struct ast_smdi_md_message *ast_smdi_md_message_wait(struct ast_smdi_interface *iface, int timeout); +struct ast_smdi_md_message *ast_smdi_md_message_wait_for_callid(struct ast_smdi_interface *iface, int timeout, char *callid); void ast_smdi_md_message_putback(struct ast_smdi_interface *iface, struct ast_smdi_md_message *msg); /* MWI message queue functions */ Index: res/res_smdi.c =================================================================== --- res/res_smdi.c (revision 54176) +++ res/res_smdi.c (working copy) @@ -245,6 +245,52 @@ } /*! + * \brief Get the specified SMDI message from the queue. + * \param iface a pointer to the interface to use. + * \param timeout the time to wait before returning in milliseconds. + * \param terminal the message desk terminal to search for in the queue.. + * + * This function pulls a message from the SMDI message queue on the specified + * interface. If no message is available this function will wait the specified + * amount of time before returning. + * + * \return the specified SMDI message, or NULL if there were no pending messages and + * the timeout has expired. + */ +extern struct ast_smdi_md_message *ast_smdi_md_message_wait_for_callid(struct ast_smdi_interface *iface, int timeout, char *terminal) +{ + struct timeval start; + long diff = 0; + struct ast_smdi_md_message *msg; + + start = ast_tvnow(); + while (diff < timeout) { + if (option_debug) + ast_log(LOG_DEBUG, "Popping SMDI message...\n"); + msg = ast_smdi_md_message_pop(iface); + while (msg != NULL) { + if (option_debug) + ast_log(LOG_DEBUG, "comparing SMDI MD terminal %s to %s\n", msg->mesg_desk_term, terminal); + if (strcmp(msg->mesg_desk_term,terminal) == 0) { + return msg; + } else { + if (option_debug) + ast_log(LOG_DEBUG, "No match, pushing SMDI message...\n"); + ast_smdi_md_message_push(iface, msg); + } + if (option_debug) + ast_log(LOG_DEBUG, "Popping SMDI message...\n"); + msg = ast_smdi_md_message_pop(iface); + } + + /* check timeout */ + diff = ast_tvdiff_ms(ast_tvnow(), start); + } + return NULL; +} + + +/*! * \brief Get the next SMDI message from the queue. * \param iface a pointer to the interface to use. *