diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 7aa271a24ab38c1313b19cbdbe078f71bbee78cc..825f6091a45e65ba333166eed6a0e27baf201ddc 100755 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -1089,6 +1089,61 @@ if (!p) { } #endif + +/* Call-back function that gets called on transfer + * + * Returns 1 on success + */ +int setup_transfer_call(unsigned call_reference, const char *extension) +{ + struct oh323_pvt *p; + struct ast_channel *c = NULL; + char exten[AST_MAX_EXTENSION]; + char *context; + + p = find_call(call_reference); + + if (!p) { + ast_log(LOG_WARNING, "No such call %d.\n", call_reference); + return -1; + } + + if (!p->owner) { + ast_log(LOG_WARNING, "Call %d has no owner.\n", call_reference); + return -1; + } + + memcpy(exten, extension, sizeof(exten)); + + c = p->owner; + if (c && c->bridge) { + strncpy(exten, extension, sizeof(exten) - 1); + context = strchr(exten, '@'); + if (context) { + *context = '\0'; + context++; + } else + context = c->context; + if (!strlen(context)) + context = c->bridge->context; + if (ast_exists_extension(c->bridge, context, exten, 1, c->bridge->callerid)) { + + ast_log(LOG_NOTICE, "Transfering call %s to %s@%s.\n", c->bridge->name, exten, context); + + if (!ast_async_goto(c->bridge, context, exten, 1, 1)) + return 1; + + ast_log(LOG_WARNING, "Failed to transfer.\n"); + } else { + ast_log(LOG_WARNING, "No such extension '%s' exists.\n", exten); + } + } else { + ast_log(LOG_WARNING, "There is no call to transfer\n"); + } + return 0; +} + + /** * Call-back function that gets called for each rtp channel opened * @@ -1714,11 +1769,13 @@ int load_module() /* Register our callback functions */ h323_callback_register(setup_incoming_call, setup_outgoing_call, + setup_transfer_call, create_connection, setup_rtp_connection, cleanup_connection, connection_made, send_digit); + /* start the h.323 listener */ if (h323_start_listener(port, bindaddr)) { ast_log(LOG_ERROR, "Unable to create H323 listener.\n"); diff --git a/channels/h323/ast_h323.cpp b/channels/h323/ast_h323.cpp index f59d086846f67cf56db34c9d517fcc981c681558..6ee771a427c443be1a45e593e3ab0f4ebe4a7f55 100755 --- a/channels/h323/ast_h323.cpp +++ b/channels/h323/ast_h323.cpp @@ -269,6 +269,24 @@ void MyH323EndPoint::OnClosedLogicalChannel(H323Connection & connection, const H H323EndPoint::OnClosedLogicalChannel(connection, channel); } +BOOL MyH323EndPoint::OnConnectionForwarded(H323Connection & connection, + const PString & forwardParty, + const H323SignalPDU & pdu) + { + if (h323debug) + cout << " -- Call Forwarded to " << forwardParty << endl; + return FALSE; + } + +BOOL MyH323EndPoint::ForwardConnection(H323Connection & connection, + const PString & forwardParty, + const H323SignalPDU & pdu) +{ + if (h323debug) + cout << " -- Forwarding call to " << forwardParty << endl; + return H323EndPoint::ForwardConnection(connection, forwardParty, pdu); +} + void MyH323EndPoint::OnConnectionEstablished(H323Connection & connection, const PString & estCallToken) { if (h323debug) @@ -389,6 +407,48 @@ H323Connection * MyH323EndPoint::CreateConnection(unsigned callReference, void * return new MyH323Connection(*this, callReference, options); } +H323Connection * MyH323EndPoint::SetupTransfer(const PString & token, + const PString & callIdentity, + const PString & remoteParty, + PString & newToken, + void * userData) +{ + PString alias; + H323TransportAddress address; + + H323Connection * connection; + + if (h323debug) { + cout << " -- Setup transfer of " << callIdentity << ":" << endl; + cout << " -- Call from " << token << endl; + cout << " -- Remote Party " << remoteParty << endl; + } + + connection = FindConnectionWithLock(token); + + if (connection != NULL) { + unsigned int old_call_reference = connection->GetCallReference(); + + if (h323debug) + cout << " -- Old call reference " << old_call_reference << endl; + connection->Unlock(); + + if (on_transfer_call(old_call_reference, remoteParty)) { + if (h323debug) + cout << " -- Transfer succeded " << endl; + if (connection->ClearCall(H323Connection::EndedByCallForwarded)) + return NULL; + return NULL; + } + } + if (h323debug) + cout << " -- Transfer failed " << endl; + + if (connection != NULL) { + return connection; + } + return NULL; +} /* MyH323Connection */ MyH323Connection::MyH323Connection(MyH323EndPoint & ep, @@ -734,16 +794,18 @@ void h323_debug(int flag, unsigned level) } /** Installs the callback functions on behalf of the PBX application */ -void h323_callback_register(setup_incoming_cb ifunc, +void h323_callback_register(setup_incoming_cb ifunc, setup_outbound_cb sfunc, + setup_transfer_cb tfunc, on_connection_cb confunc, start_logchan_cb lfunc, - clear_con_cb clfunc, - con_established_cb efunc, - send_digit_cb dfunc) + clear_con_cb clfunc, + con_established_cb efunc, + send_digit_cb dfunc) { on_incoming_call = ifunc; on_outgoing_call = sfunc; + on_transfer_call = tfunc; on_create_connection = confunc; on_start_logical_channel = lfunc; on_connection_cleared = clfunc; diff --git a/channels/h323/ast_h323.h b/channels/h323/ast_h323.h index c713a842e609233d1ad0d32a94715eea6737ee3d..9818750afb80dab832ddebcff9f97d517509ef37 100755 --- a/channels/h323/ast_h323.h +++ b/channels/h323/ast_h323.h @@ -111,8 +111,12 @@ class MyH323EndPoint : public H323EndPoint { void OnConnectionEstablished(H323Connection &, const PString &); void OnConnectionCleared(H323Connection &, const PString &); H323Connection * CreateConnection(unsigned, void *); + H323Connection * SetupTransfer(const PString &, const PString &, const PString &, PString &, void *); void SendUserTone(const PString &, char); H323Capabilities GetCapabilities(void); + BOOL OnConnectionForwarded(H323Connection &, const PString &, const H323SignalPDU &); + + BOOL ForwardConnection(H323Connection &, const PString &, const H323SignalPDU &); PStringArray SupportedPrefixes; @@ -133,14 +137,14 @@ class MyH323Connection : public H323Connection { H323Channel * CreateRealTimeLogicalChannel(const H323Capability &, H323Channel::Directions, unsigned, const H245_H2250LogicalChannelParameters *); H323Connection::AnswerCallResponse OnAnswerCall(const PString &, const H323SignalPDU &, H323SignalPDU &); + void OnReceivedReleaseComplete(const H323SignalPDU &); BOOL OnAlerting(const H323SignalPDU &, const PString &); BOOL OnSendReleaseComplete(H323SignalPDU &); BOOL OnReceivedSignalSetup(const H323SignalPDU &); - void OnReceivedReleaseComplete(const H323SignalPDU &); BOOL OnReceivedFacility(const H323SignalPDU &); BOOL OnSendSignalSetup(H323SignalPDU &); BOOL OnStartLogicalChannel(H323Channel &); - BOOL OnClosingLogicalChannel(H323Channel &); + BOOL OnClosingLogicalChannel(H323Channel &); void SendUserInputTone(char, unsigned); void OnUserInputTone(char, unsigned, unsigned, unsigned); void OnUserInputString(const PString &value); diff --git a/channels/h323/chan_h323.h b/channels/h323/chan_h323.h index 190a8244fbd3585360dcd290e34cc98abfb921b6..c1f5a90cf54879a23f746ddc599bbc739c2d80c4 100755 --- a/channels/h323/chan_h323.h +++ b/channels/h323/chan_h323.h @@ -131,6 +131,11 @@ setup_incoming_cb on_incoming_call; typedef int (*setup_outbound_cb)(call_details_t); setup_outbound_cb on_outgoing_call; +/* This is a callback prototype function, called upon + a transfer. */ +typedef int (*setup_transfer_cb)(unsigned int, const char *); +setup_transfer_cb on_transfer_call; + /* This is a callback prototype function, called when the openh323 OnStartLogicalChannel is invoked. */ typedef void (*start_logchan_cb)(unsigned int, const char *, int); @@ -164,7 +169,15 @@ extern "C" { void h323_debug(int, unsigned); /* callback function handler*/ - void h323_callback_register(setup_incoming_cb, setup_outbound_cb, on_connection_cb, start_logchan_cb, clear_con_cb, con_established_cb, send_digit_cb); + void h323_callback_register(setup_incoming_cb, + setup_outbound_cb, + setup_transfer_cb, + on_connection_cb, + start_logchan_cb, + clear_con_cb, + con_established_cb, + send_digit_cb); + int h323_set_capability(int, int); int h323_set_alias(struct oh323_alias *);