diff --git a/apps/ivr/Ivr.cpp b/apps/ivr/Ivr.cpp index 615b6a98..8b29aa35 100644 --- a/apps/ivr/Ivr.cpp +++ b/apps/ivr/Ivr.cpp @@ -464,6 +464,11 @@ void IvrFactory::start_deferred_threads() { } +int IvrDialog::transfer(const string& target) +{ + return dlg.transfer(target); +} + /** * Load a script using user name from URI. * Note: there is no default script. diff --git a/apps/ivr/Ivr.h b/apps/ivr/Ivr.h index 765f7ca9..9533163b 100644 --- a/apps/ivr/Ivr.h +++ b/apps/ivr/Ivr.h @@ -130,6 +130,8 @@ public: // must be called before everything else. void setPyPtrs(PyObject *mod, PyObject *dlg); + + int transfer(const string& target); void onSessionStart(const AmSipRequest& req); void onBye(const AmSipRequest& req); diff --git a/apps/ivr/IvrDialogBase.cpp b/apps/ivr/IvrDialogBase.cpp index 9621d704..1b64d0b7 100644 --- a/apps/ivr/IvrDialogBase.cpp +++ b/apps/ivr/IvrDialogBase.cpp @@ -140,6 +140,7 @@ static PyObject* IvrDialogBase_stopSession(IvrDialogBase* self, PyObject*) { assert(self->p_dlg); self->p_dlg->setStopped(); + self->p_dlg->postEvent(0); Py_INCREF(Py_None); return Py_None; } @@ -385,6 +386,24 @@ IvrDialogBase_getdialog(IvrDialogBase *self, void *closure) return self->dialog; } +static PyObject* +IvrDialogBase_redirect(IvrDialogBase *self, PyObject* args) +{ + assert(self->p_dlg); + + char* refer_to=0; + if(!PyArg_ParseTuple(args,"s",&refer_to)) + return NULL; + + if(self->p_dlg->transfer(refer_to)){ + ERROR("redirect failed\n"); + return NULL; + } + + Py_INCREF(Py_None); + return Py_None; + +} static PyMethodDef IvrDialogBase_methods[] = { @@ -412,7 +431,9 @@ static PyMethodDef IvrDialogBase_methods[] = { {"bye", (PyCFunction)IvrDialogBase_bye, METH_NOARGS, "Send a BYE" }, - + {"redirect", (PyCFunction)IvrDialogBase_redirect, METH_VARARGS, + "Refers the remote party to some third party." + }, // Media control {"enqueue", (PyCFunction)IvrDialogBase_enqueue, METH_VARARGS, "Add some audio to the queue (mostly IvrAudioFile)" diff --git a/core/AmSipDialog.cpp b/core/AmSipDialog.cpp index cf2e0fa6..63e8328a 100644 --- a/core/AmSipDialog.cpp +++ b/core/AmSipDialog.cpp @@ -421,6 +421,49 @@ int AmSipDialog::refer(const string& refer_to) } +int AmSipDialog::transfer(const string& target) +{ + if(status == Connected){ + + status = Disconnecting; + + string hdrs; + AmSipDialog tmp_d(*this); + + tmp_d.setRoute(""); + tmp_d.contact_uri = "Contact: <" + tmp_d.remote_uri + ">\n"; + tmp_d.remote_uri = target; + + if(!route.empty()){ + + vector::iterator it = route.begin(); + string r_set = "P-Transfer-RR: " + *it; + + for(it++; it != route.end(); it++) + r_set += "," + *it; + + hdrs += r_set + "\n"; + } + + if(!next_hop.empty()) + hdrs += "P-Transfer-NH: " + next_hop + "\n"; + + int ret = tmp_d.sendRequest("REFER","","",hdrs); + if(!ret){ + uac_trans.insert(tmp_d.uac_trans.begin(), + tmp_d.uac_trans.end()); + cseq = tmp_d.cseq; + } + + return ret; + } + + DBG("transfer(): we are not connected " + "(status=%i). do nothing!\n",status); + + return 0; +} + int AmSipDialog::cancel() { int cancel_cseq = -1; diff --git a/core/AmSipDialog.h b/core/AmSipDialog.h index 0f9882f8..ab41bd45 100644 --- a/core/AmSipDialog.h +++ b/core/AmSipDialog.h @@ -142,6 +142,8 @@ public: const string& content_type, const string& body); int refer(const string& refer_to); + int transfer(const string& target); + /** * @return true if a transaction could be found that * matches the CANCEL's one.