implement transfer and call forwarding. Bug #221
authorJeremy McNamara <jj@nufone.net>
Sat, 6 Sep 2003 20:29:25 +0000 (20:29 +0000)
committerJeremy McNamara <jj@nufone.net>
Sat, 6 Sep 2003 20:29:25 +0000 (20:29 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1482 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_h323.c
channels/h323/ast_h323.cpp
channels/h323/ast_h323.h
channels/h323/chan_h323.h

index 7aa271a..825f609 100755 (executable)
@@ -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");
index f59d086..6ee771a 100755 (executable)
@@ -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;
index c713a84..9818750 100755 (executable)
@@ -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);
index 190a824..c1f5a90 100755 (executable)
@@ -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 *);