/* Patch to add auto-answer feature for AMI Originate command. The Originate command has to set a Variable "AUTO_ANSWER_A=1". All lines marked with + have to be added in file "channels/chan_sip.c" or "channels\sip\include\sip.h". Then you have to call "make install" for your Asterisk project again. Tested with snom 360, firmware version: snom360-SIP 7.3.7 14671 Asterisk: 1.8 */ // "channels\sip\include\sip.h": struct sip_pvt { struct sip_pvt *next; /*!< Next dialog in chain */ ... struct sip_subscription_mwi *mwi; /*!< If this is a subscription MWI dialog, to which subscription */ + int addHeaderAutoAnswer; /*!< for Originate AUTO_ANSWER_A */ + char addHeaderAutoAnswerInfoLine[100]; /*!< for Originate AUTO_ANSWER_A */ }; // "channels/chan_sip.c": static int sip_call(struct ast_channel *ast, char *dest, int timeout) { ... /* Check whether there is vxml_url, distinctive ring variables */ headp=&ast->varshead; AST_LIST_TRAVERSE(headp, current, entries) { /* Check whether there is a VXML_URL variable */ //ast_log(LOG_WARNING, "ast_var_name=%s\n",ast_var_name(current)); if (!p->options->vxml_url && !strcasecmp(ast_var_name(current), "VXML_URL")) { p->options->vxml_url = ast_var_value(current); } else if (!p->options->uri_options && !strcasecmp(ast_var_name(current), "SIP_URI_OPTIONS")) { p->options->uri_options = ast_var_value(current); } else if (!p->options->addsipheaders && !strncasecmp(ast_var_name(current), "SIPADDHEADER", strlen("SIPADDHEADER"))) { /* Check whether there is a variable with a name starting with SIPADDHEADER */ p->options->addsipheaders = 1; } else if (!strcasecmp(ast_var_name(current), "SIPFROMDOMAIN")) { ast_string_field_set(p, fromdomain, ast_var_value(current)); } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER")) { /* This is a transfered call */ p->options->transfer = 1; } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REFERER")) { /* This is the referrer */ referer = ast_var_value(current); } else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REPLACES")) { /* We're replacing a call. */ p->options->replaces = ast_var_value(current); } else if (!strcasecmp(ast_var_name(current), "T38CALL")) { p->t38.state = T38_LOCAL_DIRECT; ast_debug(1, "T38State change to %d on channel %s\n", p->t38.state, ast->name); + } else if (!strcasecmp(ast_var_name(current), "AUTO_ANSWER_A")) { + const char *value = ast_var_value(current); + p->addHeaderAutoAnswer = atoi(value); + const char *infoLine = strchr(value,';'); + if ( infoLine ) + strncpy(p->addHeaderAutoAnswerInfoLine,&infoLine[1],sizeof(p->addHeaderAutoAnswerInfoLine)); } } ... } static int transmit_invite(struct sip_pvt *p, int sipmethod, int sdp, int init) { ... /* This new INVITE is part of an attended transfer. Make sure that the other end knows and replace the current call with this new call */ if (p->options && !ast_strlen_zero(p->options->replaces)) { add_header(&req, "Replaces", p->options->replaces); add_header(&req, "Require", "replaces"); } + if ( p->addHeaderAutoAnswer ) /* if Originate sets a variable: AUTO_ANSWER_A=1..n */ + { + const char *infoFmt = ""; + switch ( p->addHeaderAutoAnswer ) + { + case 2: infoFmt = "Call-Info: answer-after=0"; break; // Mode2 (ohne IP) + case 4: infoFmt = "Alert-Info: info=alert-autoanswer"; break; // Aastra 5xi + case 5: infoFmt = "Alert-Info: Auto Answer"; break; // Polycom + case 8: infoFmt = "Alert-Info: ;info=alert-autoanswer"; break; // OpenStage + case 10: infoFmt = p->addHeaderAutoAnswerInfoLine; break; // User-defined Info Header + default: infoFmt = "Call-Info: \\;answer-after=0"; break; // Standard: Lyncsys, Snom, Grandstream, Snom, Tiptel + } + if ( *infoFmt ) + { + char info[100]; + //snprintf(info, sizeof(info), infoFmt, ast_inet_ntoa(p->ourip.sin_addr)); // Asterisk 1.6 + snprintf(info, sizeof(info), infoFmt, ast_sockaddr_stringify_addr(&p->ourip)); // Asterisk 1.8 + char *infoParams = strchr(info,':'); + if ( infoParams ) + { + infoParams[0] = 0; + add_header(&req, info, &infoParams[2]); + } + } + } /* Add Session-Timers related headers */ ... }