+ send_message(message_type, call->bridge_call->ref, param);
+}
+
+/*
+ * check if extension matches and start asterisk
+ * if it can match, proceed
+ * if not, release
+ */
+static void lcr_setup_pbx(struct chan_call *call, struct ast_channel *ast, int complete)
+{
+ int cause;
+
+ if (complete)
+ {
+ /* if not match */
+ if (!ast_canmatch_extension(ast, ast->context, call->dad, 1, call->oad))
+ {
+ cause = 1;
+ goto release;
+ if (!ast_exists_extension(ast, ast->context, call->dad, 1, call->oad))
+ {
+ cause = 28;
+ goto release;
+ }
+ /* send setup acknowledge to lcr */
+ memset(&newparam, 0, sizeof(union parameter));
+ send_message(MESSAGE_PROCEEDING, call->ref, &newparam);
+
+ /* change state */
+ call->state = CHAN_LCR_STATE_IN_PROCEEDING;
+
+ goto start;
+ }
+
+ if (ast_canmatch_extension(ast, ast->context, dad, 1, oad))
+ {
+ /* send setup acknowledge to lcr */
+ memset(&newparam, 0, sizeof(union parameter));
+ send_message(MESSAGE_OVERLAP, call->ref, &newparam);
+
+ /* change state */
+ call->state = CHAN_LCR_STATE_IN_DIALING;
+
+ /* if match, start pbx */
+ if (ast_exists_extension(ast, ast->context, dad, 1, oad))
+ goto start;
+
+ /* if can match */
+ return;
+ }
+
+ /* if not match */
+ cause = 1;
+ release:
+ /* release lcr */
+ memset(&newparam, 0, sizeof(union parameter));
+ newparam.disconnectinfo.cause = cause;
+ newparam.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+ send_message(MESSAGE_RELEASE, call->ref, &newparam);
+ call->ref = 0;
+ /* release asterisk */
+ ast->hangupcause = call->cause;
+ ast_queue_hangup(ast);
+ /* change to release state */
+ call->state = CHAN_LCR_STATE_RELEASE;
+ return;
+
+ start:
+ /* send setup to asterisk */
+ ret = ast_pbx_start(ast);
+ if (ret < 0)
+ {
+ cause = (ret==-2)?34:27;
+ goto release;
+ }
+ call->pbx_started = 1;
+ return;