[Asterisk-Users] Several H323 bugfixes - working SIP <-> H.323 translator
Marian Durkovic
md at bts.sk
Thu Mar 18 08:35:04 MST 2004
Hi all,
in an effort to create a SIP <-> H.323 translator we've found and fixed
several problems in H.323 channel. These inlcude:
for SIP->H.323 calls
- no ringback tone
- ringback not related to H.323 events
- one-way audio with Cisco CallManager
- incorrect Caller ID
for H.323->SIP calls
- not able to establish call with Cisco IOS 12.3(4)T
- ringback not related to SIP events
- no support for 183 Call Progress
- incorrect Caller ID
Please find the patches against aterisk 0.7.2 release below.
M.
--------------------------------------------------------------------------
---- ----
---- Marian Durkovic network manager ----
---- ----
---- Slovak Technical University Tel: +421 2 524 51 301 ----
---- Computer Centre, Nam. Slobody 17 Fax: +421 2 524 94 351 ----
---- 812 43 Bratislava, Slovak Republic E-mail/sip: md at bts.sk ----
---- ----
--------------------------------------------------------------------------
-------------- next part --------------
--- chan_h323.h.072 Tue Jan 13 09:46:46 2004
+++ chan_h323.h Thu Mar 18 16:03:11 2004
@@ -84,6 +84,7 @@
function*/
typedef struct call_options {
char *callerid;
+ char *callername;
int noFastStart;
int noH245Tunnelling;
int noSilenceSuppression;
@@ -101,6 +102,7 @@
const char *call_dest_alias;
const char *call_source_e164;
const char *call_dest_e164;
+ const char *call_source_name;
const char *sourceIp;
} call_details_t;
@@ -134,6 +136,11 @@
typedef void (*start_logchan_cb)(unsigned int, const char *, int);
start_logchan_cb on_start_logical_channel;
+/* This is a callback prototype function, called when openh323
+ OnAlerting is invoked */
+typedef void (*chan_ringing_cb)(unsigned);
+chan_ringing_cb on_chan_ringing;
+
/* This is a callback protoype function, called when the openh323
OnConnectionEstablished is inovked */
typedef void (*con_established_cb)(unsigned);
@@ -167,6 +174,7 @@
on_connection_cb,
start_logchan_cb,
clear_con_cb,
+ chan_ringing_cb,
con_established_cb,
send_digit_cb);
@@ -189,6 +197,8 @@
/* H323 create and destroy sessions */
int h323_make_call(char *host, call_details_t *cd, call_options_t);
int h323_clear_call(const char *);
+ int h323_send_alerting(const char *token);
+ int h323_send_progress(const char *token);
int h323_answering_call(const char *token, int);
int h323_soft_hangup(const char *data);
-------------- next part --------------
--- chan_h323.c.072 Tue Jan 13 10:24:26 2004
+++ chan_h323.c Thu Mar 18 16:09:40 2004
@@ -388,7 +389,7 @@
int res;
struct oh323_pvt *p = c->pvt->pvt;
char called_addr[256];
- char *tmp;
+ char *tmp, *cid, *cidname, oldcid[256];
strtok_r(dest, "/", &(tmp));
@@ -419,15 +420,47 @@
/* Copy callerid, if there is any */
if (c->callerid) {
- char *tmp = strchr(c->callerid, '"');
- if (!tmp) {
- p->calloptions.callerid = malloc(80); // evil
- // sprintf(p->calloptions.callerid, "\"%s\"", c->callerid);
- sprintf(p->calloptions.callerid, "\"\" <%s>", c->callerid);
- } else {
- p->calloptions.callerid = strdup(c->callerid);
- }
- }
+ memset(oldcid, 0, sizeof(oldcid));
+ memcpy(oldcid, c->callerid, strlen(c->callerid));
+ oldcid[sizeof(oldcid)-1] = '\0';
+ ast_callerid_parse(oldcid, &cidname, &cid);
+ if (p->calloptions.callerid) {
+ free(p->calloptions.callerid);
+ p->calloptions.callerid = NULL;
+ }
+ if (p->calloptions.callername) {
+ free(p->calloptions.callername);
+ p->calloptions.callername = NULL;
+ }
+ p->calloptions.callerid = (char*)malloc(256);
+ if (p->calloptions.callerid == NULL) {
+ ast_log(LOG_ERROR, "Not enough memory.\n");
+ return(-1);
+ }
+ memset(p->calloptions.callerid, 0, 256);
+ if ((cid != NULL)&&(strlen(cid) > 0))
+ strncpy(p->calloptions.callerid, cid, 255);
+
+ p->calloptions.callername = (char*)malloc(256);
+ if (p->calloptions.callername == NULL) {
+ ast_log(LOG_ERROR, "Not enough memory.\n");
+ return(-1);
+ }
+ memset(p->calloptions.callername, 0, 256);
+ if ((cidname != NULL)&&(strlen(cidname) > 0))
+ strncpy(p->calloptions.callername, cidname, 255);
+
+ } else {
+ if (p->calloptions.callerid) {
+ free(p->calloptions.callerid);
+ p->calloptions.callerid = NULL;
+ }
+ if (p->calloptions.callername) {
+ free(p->calloptions.callername);
+ p->calloptions.callername = NULL;
+ }
+ }
+
res = h323_make_call(called_addr, &(p->cd), p->calloptions);
@@ -436,7 +469,6 @@
return -1;
}
- ast_setstate(c, AST_STATE_RINGING);
return 0;
}
@@ -592,27 +624,33 @@
switch(condition) {
case AST_CONTROL_RINGING:
- if (c->_state == AST_STATE_RING) {
- // transmit_response(p, "180 Ringing", &p->initreq);
+ if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) {
+ h323_send_alerting(p->cd.call_token);
break;
}
- return 0;
+ return -1;
+ case AST_CONTROL_PROGRESS:
+ if (c->_state != AST_STATE_UP) {
+ h323_send_progress(p->cd.call_token);
+ break;
+ }
+ return -1;
case AST_CONTROL_BUSY:
if (c->_state != AST_STATE_UP) {
- // transmit_response(p, "600 Busy everywhere", &p->initreq);
+ h323_answering_call(p->cd.call_token, 1);
p->alreadygone = 1;
- ast_softhangup(c, AST_SOFTHANGUP_DEV);
+ ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
break;
}
- return 0;
+ return -1;
case AST_CONTROL_CONGESTION:
if (c->_state != AST_STATE_UP) {
- // transmit_response(p, "486 Busy here", &p->initreq);
+ h323_answering_call(p->cd.call_token, 1);
p->alreadygone = 1;
- ast_softhangup(c, AST_SOFTHANGUP_DEV);
+ ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV);
break;
}
- return 0;
+ return -1;
case -1:
return -1;
default:
@@ -985,11 +1023,12 @@
p->cd.call_dest_alias = cd.call_dest_alias;
p->cd.call_source_e164 = cd.call_source_e164;
p->cd.call_dest_e164 = cd.call_dest_e164;
+ p->cd.call_source_name = cd.call_source_name;
if (h323debug) {
ast_verbose(VERBOSE_PREFIX_3 "Setting up Call\n");
ast_verbose(VERBOSE_PREFIX_3 " Call token: [%s]\n", p->cd.call_token);
- ast_verbose(VERBOSE_PREFIX_3 " Calling party name: [%s]\n", p->cd.call_source_aliases);
+ ast_verbose(VERBOSE_PREFIX_3 " Calling party name: [%s]\n", p->cd.call_source_name);
ast_verbose(VERBOSE_PREFIX_3 " Calling party number: [%s]\n", p->cd.call_source_e164);
ast_verbose(VERBOSE_PREFIX_3 " Called party name: [%s]\n", p->cd.call_dest_alias);
ast_verbose(VERBOSE_PREFIX_3 " Called party number: [%s]\n", p->cd.call_dest_e164);
@@ -1013,7 +1052,7 @@
}
- sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164);
+ sprintf(p->callerid, "%s <%s>", p->cd.call_source_name, p->cd.call_source_e164);
} else {
/* Either this call is not from the Gatekeeper
@@ -1024,7 +1063,7 @@
if (!user) {
- sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164);
+ sprintf(p->callerid, "%s <%s>", p->cd.call_source_name, p->cd.call_source_e164);
if (strlen(p->cd.call_dest_e164)) {
strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1);
} else {
@@ -1064,7 +1103,7 @@
if (strlen(user->callerid))
strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1);
else
- sprintf(p->callerid, "%s <%s>", p->cd.call_source_aliases, p->cd.call_source_e164);
+ sprintf(p->callerid, "%s <%s>", p->cd.call_source_name, p->cd.call_source_e164);
if (strlen(p->cd.call_dest_e164)) {
strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1);
@@ -1162,8 +1201,38 @@
c = p->owner;
ast_setstate(c, AST_STATE_UP);
+ ast_queue_control(c, AST_CONTROL_ANSWER, 0);
+
return;
}
+/**
+ * Call-back function to signal asterisk that the channel is ringing
+
+ * Returns nothing
+ */
+
+void chan_ringing(unsigned call_reference)
+{
+ struct ast_channel *c = NULL;
+ struct oh323_pvt *p = NULL;
+
+ p = find_call(call_reference);
+
+ if (!p)
+ ast_log(LOG_ERROR, "Something is wrong: ringing\n");
+
+
+ if (!p->owner) {
+ ast_log(LOG_ERROR, "Channel has no owner\n");
+ return;
+ }
+ c = p->owner;
+ ast_setstate(c, AST_STATE_RINGING);
+ ast_queue_control(c, AST_CONTROL_RINGING, 0);
+
+ return;
+}
+
/**
* Call-back function to cleanup communication
@@ -1793,6 +1862,7 @@
create_connection,
setup_rtp_connection,
cleanup_connection,
+ chan_ringing,
connection_made,
send_digit);
-------------- next part --------------
--- ast_h323.h.072 Tue Jan 13 04:06:06 2004
+++ ast_h323.h Thu Mar 18 16:00:46 2004
@@ -198,7 +198,7 @@
public:
- int MakeCall(const PString &, PString &, unsigned int *, unsigned int, char *);
+ int MakeCall(const PString &, PString &, unsigned int *, unsigned int, char *, char *);
BOOL ClearCall(const PString &);
void OnClosedLogicalChannel(H323Connection &, const H323Channel &);
@@ -252,6 +252,45 @@
WORD sessionId;
BOOL bridging; // Used to help determine which IP to use
};
+
+class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel {
+
+ PCLASSINFO(MyH323_ExternalRTPChannel, H323_ExternalRTPChannel);
+
+ public:
+ MyH323_ExternalRTPChannel(
+ MyH323Connection & connection, /// Connection to endpoint for channel
+ const H323Capability & capability, /// Capability channel is using
+ Directions direction, /// Direction of channel
+ unsigned sessionID /// Session ID for channel
+ );
+ MyH323_ExternalRTPChannel(
+ MyH323Connection & connection, /// Connection to endpoint for channel
+ const H323Capability & capability, /// Capability channel is using
+ Directions direction, /// Direction of channel
+ unsigned sessionID, /// Session ID for channel
+ const H323TransportAddress & data, /// Data address
+ const H323TransportAddress & control/// Control address
+ );
+ /**Create a new channel.
+ */
+ MyH323_ExternalRTPChannel(
+ MyH323Connection & connection, /// Connection to endpoint for channel
+ const H323Capability & capability, /// Capability channel is using
+ Directions direction, /// Direction of channel
+ unsigned sessionID, /// Session ID for channel
+ const PIPSocket::Address & ip, /// IP address of media server
+ WORD dataPort /// Data port (control is dataPort+1)
+ );
+
+ BOOL OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param);
+
+ PIPSocket::Address externalIpAddress; // IP address of media server
+ PIPSocket::Address remoteIpAddress; // IP Address of remote
+ WORD externalPort; // local media s
+ WORD remotePort;
+
+};
/**
* The MyProcess is a necessary descendant PProcess class so that the H323EndPoint
-------------- next part --------------
--- ast_h323.cpp.072 Tue Jan 13 09:31:13 2004
+++ ast_h323.cpp Thu Mar 18 16:12:58 2004
@@ -219,7 +219,7 @@
* port = 1720.
*/
int MyH323EndPoint::MakeCall(const PString & dest, PString & token,
- unsigned int *callReference, unsigned int port, char *callerid)
+ unsigned int *callReference, unsigned int port, char *callerid, char *callername)
{
PString fullAddress;
MyH323Connection * connection;
@@ -243,8 +243,15 @@
*callReference = connection->GetCallReference();
- if (callerid)
- connection->SetLocalPartyName(PString(callerid));
+ if (callername) {
+ localAliasNames.RemoveAll();
+ connection->SetLocalPartyName(PString(callername));
+ if (callerid)
+ localAliasNames.AppendString(PString(callerid));
+ } else if (callerid) {
+ localAliasNames.RemoveAll();
+ connection->SetLocalPartyName(PString(callerid));
+ }
connection->Unlock();
@@ -447,6 +454,8 @@
if (noH245Tunnelling)
options |= H323Connection::H245TunnelingOptionDisable;
+ SetAudioJitterDelay(10, 50);
+
return new MyH323Connection(*this, callReference, options);
}
@@ -478,7 +487,7 @@
{
/* The call will be answered later with "AnsweringCall()" function.
*/
- return H323Connection::AnswerCallAlertWithMedia;
+ return H323Connection::AnswerCallDeferred;
}
BOOL MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username)
@@ -487,6 +496,7 @@
if (h323debug) {
cout << " -- Ringing phone for \"" << username << "\"" << endl;
}
+ on_chan_ringing(GetCallReference());
return TRUE;
}
@@ -499,6 +509,7 @@
call_details_t cd;
PString sourceE164;
+ PString sourceName;
PString destE164;
PString sourceAliases;
PString destAliases;
@@ -511,6 +522,8 @@
sourceE164 = "";
setupPDU.GetSourceE164(sourceE164);
+ sourceName = "";
+ sourceName=setupPDU.GetQ931().GetDisplayName();
destE164 = "";
setupPDU.GetDestinationE164(destE164);
@@ -538,6 +551,7 @@
cd.call_source_e164 = (const char *)sourceE164;
cd.call_dest_e164 = (const char *)destE164;
cd.sourceIp = (const char *)sourceIp;
+ cd.call_source_name = (const char *)sourceName;
/* Notify Asterisk of the request */
int res = on_incoming_call(cd);
@@ -683,7 +697,7 @@
cout << " -- SessionID: " << sessionID << endl;
cout << " -- Direction: " << dir << endl;
}
- return new H323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
+ return new MyH323_ExternalRTPChannel(*this, capability, dir, sessionID, externalIpAddress, externalPort);
}
/** This callback function is invoked once upon creation of each
@@ -717,6 +731,49 @@
}
+MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
+ const H323Capability & capability,
+ Directions direction,
+ unsigned id)
+:
+H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id)
+{
+}
+
+MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection, const H323Capability & capability,
+ Directions direction,
+ unsigned id,
+ const H323TransportAddress & data,
+ const H323TransportAddress & control) : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id, data, control)
+{
+}
+
+MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection,
+ const H323Capability & capability,
+ Directions direction,
+ unsigned id,
+ const PIPSocket::Address & ip,
+ WORD dataPort)
+ : H323_ExternalRTPChannel::H323_ExternalRTPChannel(connection, capability, direction, id, ip, dataPort)
+{
+}
+
+BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param)
+{
+ H323_ExternalRTPChannel::OnReceivedAckPDU(param);
+
+ H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddress, remotePort);
+
+ if (h323debug) {
+ cout << " -- remoteIpAddress: " << remoteIpAddress << endl;
+ cout << " -- remotePort: " << remotePort << endl;
+ }
+ /* Notify Asterisk of remote RTP information */
+ on_start_logical_channel(connection.GetCallReference(), (const char *)remoteIpAddress.AsString(), remotePort);
+
+ return TRUE;
+}
+
/** IMPLEMENTATION OF C FUNCTIONS */
/**
@@ -772,6 +829,7 @@
on_connection_cb confunc,
start_logchan_cb lfunc,
clear_con_cb clfunc,
+ chan_ringing_cb rfunc,
con_established_cb efunc,
send_digit_cb dfunc)
{
@@ -780,6 +838,7 @@
on_create_connection = confunc;
on_start_logical_channel = lfunc;
on_connection_cleared = clfunc;
+ on_chan_ringing = rfunc;
on_connection_established = efunc;
on_send_digit = dfunc;
}
@@ -1011,7 +1070,7 @@
PString dest(host);
- res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid);
+ res = endPoint->MakeCall(dest, token, &cd->call_reference, call_options.port, call_options.callerid, call_options.callername);
memcpy((char *)(cd->call_token), (const unsigned char *)token, token.GetLength());
return res;
@@ -1026,6 +1085,47 @@
endPoint->ClearCall(PString(call_token));
return 0;
};
+
+/* Send Alerting PDU to H.323 caller */
+
+int h323_send_alerting(const char *token)
+{
+ const PString currentToken(token);
+ H323Connection * connection;
+
+ connection = endPoint->FindConnectionWithLock(currentToken);
+
+ if (connection == NULL) {
+ cout << "No connection found for " << token << endl;
+ return -1;
+ }
+
+ connection->AnsweringCall(H323Connection::AnswerCallPending);
+ connection->Unlock();
+
+ return 0;
+
+}
+
+/* Send Progress PDU to H.323 caller */
+
+int h323_send_progress(const char *token)
+{
+ const PString currentToken(token);
+ H323Connection * connection;
+
+ connection = endPoint->FindConnectionWithLock(currentToken);
+
+ if (connection == NULL) {
+ cout << "No connection found for " << token << endl;
+ return -1;
+ }
+
+ connection->AnsweringCall(H323Connection::AnswerCallDeferredWithMedia);
+ connection->Unlock();
+
+ return 0;
+}
/** This function tells the h.323 stack to either
answer or deny an incoming call */
More information about the asterisk-users
mailing list