unsigned short callno = PTR_TO_CALLNO(c->tech_pvt);
struct iax_ie_data ied = { "", };
char tmp[256], *context;
+ enum ast_control_transfer message = AST_TRANSFER_SUCCESS;
ast_copy_string(tmp, dest, sizeof(tmp));
context = strchr(tmp, '@');
if (context) {
if (context)
iax_ie_append_str(&ied, IAX_IE_CALLED_CONTEXT, context);
ast_debug(1, "Transferring '%s' to '%s'\n", c->name, dest);
+ ast_queue_control_data(c, AST_CONTROL_TRANSFER, &message, sizeof(message));
return send_command_locked(callno, AST_FRAME_IAX, IAX_COMMAND_TRANSFER, 0, ied.buf, ied.pos, -1);
}
*/
static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno)
{
+ enum ast_control_transfer message = AST_TRANSFER_FAILED;
+
/* If no refer structure exists, then do nothing */
if (!p->refer)
return;
if (ast_strlen_zero(p->authname)) {
ast_log(LOG_WARNING, "Asked to authenticate REFER to %s:%d but we have no matching peer or realm auth!\n",
ast_inet_ntoa(p->recv.sin_addr), ntohs(p->recv.sin_port));
+ if (p->owner) {
+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
+ }
pvt_set_needdestroy(p, "unable to authenticate REFER");
}
if (p->authtries > 1 || do_proxy_auth(p, req, resp, SIP_REFER, 0)) {
ast_log(LOG_NOTICE, "Failed to authenticate on REFER to '%s'\n", get_header(&p->initreq, "From"));
p->refer->status = REFER_NOAUTH;
- pvt_set_needdestroy(p, "failed to authenticat REFER");
+ if (p->owner) {
+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
+ }
+ pvt_set_needdestroy(p, "failed to authenticate REFER");
}
break;
case 481: /* Call leg does not exist */
ast_log(LOG_NOTICE, "SIP transfer to %s failed, call miserably fails. \n", p->refer->refer_to);
pvt_set_needdestroy(p, "received 500/501 response");
p->refer->status = REFER_FAILED;
+ if (p->owner) {
+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
+ }
break;
case 603: /* Transfer declined */
ast_log(LOG_NOTICE, "SIP transfer to %s declined, call miserably fails. \n", p->refer->refer_to);
p->refer->status = REFER_FAILED;
pvt_set_needdestroy(p, "received 603 response");
+ if (p->owner) {
+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
+ }
break;
}
}
if (!success) {
ast_log(LOG_NOTICE, "Transfer failed. Sorry. Nothing further to do with this call\n");
}
-
+
+ if (p->owner) {
+ enum ast_control_transfer message = success ? AST_TRANSFER_SUCCESS : AST_TRANSFER_FAILED;
+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
+ }
/* Confirm that we received this packet */
transmit_response(p, "200 OK", req);
} else if (p->mwi && !strcmp(event, "message-summary")) {
sip_scheddestroy(p, SIP_TRANS_TIMEOUT); /* Make sure we stop send this reply. */
sip_alreadygone(p);
+
+ if (p->owner) {
+ enum ast_control_transfer message = AST_TRANSFER_SUCCESS;
+ ast_queue_control_data(p->owner, AST_CONTROL_TRANSFER, &message, sizeof(message));
+ }
/* hangup here */
return 0;
}
AST_CONTROL_VIDUPDATE = 18, /*!< Indicate video frame update */
AST_CONTROL_T38 = 19, /*!< T38 state change request/notification */
AST_CONTROL_SRCUPDATE = 20, /*!< Indicate source of media has changed */
+ AST_CONTROL_TRANSFER = 21, /*!< Indicate status of a transfer request */
};
enum ast_control_t38 {
AST_T38_REFUSED /*!< T38 refused for some reason (usually rejected by remote end) */
};
+enum ast_control_transfer {
+ AST_TRANSFER_SUCCESS = 0, /*!< Transfer request on the channel worked */
+ AST_TRANSFER_FAILED, /*!< Transfer request on the channel failed */
+};
+
#define AST_SMOOTHER_FLAG_G729 (1 << 0)
#define AST_SMOOTHER_FLAG_BE (1 << 1)
case AST_CONTROL_ANSWER:
case AST_CONTROL_HANGUP:
case AST_CONTROL_T38:
+ case AST_CONTROL_TRANSFER:
return 0;
case AST_CONTROL_CONGESTION:
case AST_CONTROL_HOLD:
case AST_CONTROL_UNHOLD:
case AST_CONTROL_T38:
+ case AST_CONTROL_TRANSFER:
/* Nothing left to do for these. */
res = 0;
break;
res = 0;
}
ast_channel_unlock(chan);
+
+ if (res < 0) {
+ return res;
+ }
+
+ for (;;) {
+ struct ast_frame *fr;
+
+ res = ast_waitfor(chan, -1);
+
+ if (res < 0 || !(fr = ast_read(chan))) {
+ res = -1;
+ break;
+ }
+
+ if (fr->frametype == AST_FRAME_CONTROL && fr->subclass == AST_CONTROL_TRANSFER) {
+ enum ast_control_transfer *message = fr->data.ptr;
+
+ if (*message == AST_TRANSFER_SUCCESS) {
+ res = 1;
+ } else {
+ res = -1;
+ }
+
+ ast_frfree(fr);
+ break;
+ }
+
+ ast_frfree(fr);
+ }
+
return res;
}