From b4c39b43b961597c08f1a2d8759d4f83ba9a3013 Mon Sep 17 00:00:00 2001 From: jeremy Date: Thu, 20 May 2004 07:07:18 +0000 Subject: properly send call progress and alerting PDUs, re-fix one-way audio on call manager, and hopefully add call progress (N+101) support (not tested) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@3023 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_h323.c | 129 +++++++++++++++++++++++++++++++++------------ channels/h323/ast_h323.cpp | 114 +++++++++++++++++++++++++++++---------- channels/h323/ast_h323.h | 68 ++++++++++++++++-------- channels/h323/chan_h323.h | 38 ++++++++----- 4 files changed, 252 insertions(+), 97 deletions(-) (limited to 'channels') diff --git a/channels/chan_h323.c b/channels/chan_h323.c index 6151f6846..1f64e45a4 100755 --- a/channels/chan_h323.c +++ b/channels/chan_h323.c @@ -393,7 +393,7 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout) 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)); @@ -424,15 +424,46 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout) /* 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); @@ -440,12 +471,9 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout) ast_log(LOG_NOTICE, "h323_make_call failed(%s)\n", c->name); return -1; } - - ast_setstate(c, AST_STATE_RINGING); return 0; } - static int oh323_answer(struct ast_channel *c) { int res; @@ -597,24 +625,34 @@ static int oh323_indicate(struct ast_channel *c, int condition) switch(condition) { case AST_CONTROL_RINGING: - if (c->_state == AST_STATE_RING) { - return -1; + if (c->_state == AST_STATE_RING || c->_state == AST_STATE_RINGING) { + h323_send_alerting(p->cd.call_token); + break; + } + return -1; + case AST_CONTROL_PROGRESS: + if (c->_state != AST_STATE_UP) { + h323_send_progress(p->cd.call_token); + break; } - return 0; + return -1; + case AST_CONTROL_BUSY: if (c->_state != AST_STATE_UP) { - p->alreadygone = 1; - ast_softhangup(c, AST_SOFTHANGUP_DEV); + h323_answering_call(p->cd.call_token, 1); + p->alreadygone = 1; + ast_softhangup_nolock(c, AST_SOFTHANGUP_DEV); break; } - return 0; + return -1; case AST_CONTROL_CONGESTION: if (c->_state != AST_STATE_UP) { + 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: @@ -986,13 +1024,14 @@ int setup_incoming_call(call_details_t cd) p->cd.call_token = cd.call_token; p->cd.call_source_aliases = cd.call_source_aliases; p->cd.call_dest_alias = cd.call_dest_alias; + p->cd.call_source_name = cd.call_source_name; p->cd.call_source_e164 = cd.call_source_e164; p->cd.call_dest_e164 = cd.call_dest_e164; 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); @@ -1014,17 +1053,14 @@ int setup_incoming_call(call_details_t cd) strncpy(p->exten, alias->name, sizeof(p->exten)-1); strncpy(p->context, alias->context, sizeof(p->context)-1); } - - - 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 or we are not allowing gk routed calls */ user = find_user(cd); 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 (!ast_strlen_zero(p->cd.call_dest_e164)) { strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1); } else { @@ -1061,11 +1097,11 @@ int setup_incoming_call(call_details_t cd) p->bridge = user->bridge; p->nat = user->nat; - if (!ast_strlen_zero(user->callerid)) + if (!ast_strlen_zero(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); - + } else { + sprintf(p->callerid, "%s <%s>", p->cd.call_source_name, p->cd.call_source_e164); + } if (!ast_strlen_zero(p->cd.call_dest_e164)) { strncpy(p->exten, cd.call_dest_e164, sizeof(p->exten)-1); } else { @@ -1161,9 +1197,35 @@ void connection_made(unsigned call_reference) c = p->owner; ast_setstate(c, AST_STATE_UP); + ast_queue_control(c, AST_CONTROL_ANSWER); 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); + return; +} + /** * Call-back function to cleanup communication * Returns nothing, @@ -1171,7 +1233,7 @@ void connection_made(unsigned call_reference) void cleanup_connection(call_details_t cd) { struct oh323_pvt *p = NULL; -// struct oh323_peer *peer = NULL; +/* struct oh323_peer *peer = NULL; */ struct oh323_user *user = NULL; struct ast_rtp *rtp = NULL; @@ -1793,6 +1855,7 @@ int load_module() create_connection, setup_rtp_connection, cleanup_connection, + chan_ringing, connection_made, send_digit); @@ -1800,7 +1863,6 @@ int load_module() /* start the h.323 listener */ if (h323_start_listener(port, bindaddr)) { ast_log(LOG_ERROR, "Unable to create H323 listener.\n"); -// h323_end_process(); return -1; } @@ -1808,7 +1870,6 @@ int load_module() if (gatekeeper_disable == 0) { if (h323_set_gk(gatekeeper_discover, gatekeeper, secret)) { ast_log(LOG_ERROR, "Gatekeeper registration failed.\n"); -// h323_end_process(); return 0; } } diff --git a/channels/h323/ast_h323.cpp b/channels/h323/ast_h323.cpp index 867ccd9e6..9bb122fc6 100755 --- a/channels/h323/ast_h323.cpp +++ b/channels/h323/ast_h323.cpp @@ -218,8 +218,7 @@ H323Codec * AST_G729ACapability::CreateCodec(H323Codec::Direction direction) con * transport = ip. * port = 1720. */ -int MyH323EndPoint::MakeCall(const PString & dest, PString & token, - unsigned int *callReference, unsigned int port, char *callerid) +int MyH323EndPoint::MakeCall(const PString & dest, PString & token, unsigned int *callReference, unsigned int port, char *callerid, char *callername) { PString fullAddress; MyH323Connection * connection; @@ -245,6 +244,15 @@ int MyH323EndPoint::MakeCall(const PString & dest, PString & token, 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(); @@ -486,7 +494,7 @@ H323Connection::AnswerCallResponse MyH323Connection::OnAnswerCall(const PString { /* The call will be answered later with "AnsweringCall()" function. */ - return H323Connection::AnswerCallAlertWithMedia; + return H323Connection::AnswerCallDeferred; } BOOL MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const PString & username) @@ -495,6 +503,7 @@ BOOL MyH323Connection::OnAlerting(const H323SignalPDU & /*alertingPDU*/, const if (h323debug) { cout << " -- Ringing phone for \"" << username << "\"" << endl; } + on_chan_ringing(GetCallReference()); return TRUE; } @@ -508,6 +517,7 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU) call_details_t cd; PString sourceE164; PString destE164; + PString sourceName; PString sourceAliases; PString destAliases; PIPSocket::Address Ip; @@ -519,6 +529,8 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU) sourceE164 = ""; setupPDU.GetSourceE164(sourceE164); + sourceName = ""; + sourceName=setupPDU.GetQ931().GetDisplayName(); destE164 = ""; setupPDU.GetDestinationE164(destE164); @@ -540,6 +552,7 @@ BOOL MyH323Connection::OnReceivedSignalSetup(const H323SignalPDU & setupPDU) cd.call_dest_alias = (const char *)destAliases; cd.call_source_e164 = (const char *)sourceE164; cd.call_dest_e164 = (const char *)destE164; + cd.call_source_name = (const char *)sourceName; GetSignallingChannel()->GetRemoteAddress().GetIpAndPort(Ip, sourcePort); cd.sourceIp = (const char *)Ip.AsString(); @@ -727,11 +740,11 @@ BOOL MyH323Connection::OnStartLogicalChannel(H323Channel & channel) /* MyH323_ExternalRTPChannel */ MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connection, - const H323Capability & capability, - Directions direction, - unsigned sessionID, - const PIPSocket::Address & ip, - WORD dataPort) + const H323Capability & capability, + Directions direction, + unsigned sessionID, + const PIPSocket::Address & ip, + WORD dataPort) : H323_ExternalRTPChannel(connection, capability, direction, sessionID, ip, dataPort) { if (h323debug) { @@ -740,6 +753,24 @@ MyH323_ExternalRTPChannel::MyH323_ExternalRTPChannel(MyH323Connection & connecti return; } +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() { if (h323debug) { @@ -748,29 +779,17 @@ MyH323_ExternalRTPChannel::~MyH323_ExternalRTPChannel() return; } -BOOL MyH323_ExternalRTPChannel::OnReceivedPDU( - const H245_H2250LogicalChannelParameters & param, - unsigned & errorCode) -{ - if (h323debug) { - cout << " MyH323_ExternalRTPChannel::OnReceivedPDU " << endl; - } - return H323_ExternalRTPChannel::OnReceivedPDU( param, errorCode ); -} - -BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU( - const H245_H2250LogicalChannelAckParameters & param) +BOOL MyH323_ExternalRTPChannel::OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param) { - - PIPSocket::Address remoteIpAddress; // IP Address of remote endpoint - WORD remotePort; // remote endpoint Data port (control is dataPort+1) + PIPSocket::Address remoteIpAddress; + WORD remotePort; if (h323debug) { cout << " MyH323_ExternalRTPChannel::OnReceivedAckPDU " << endl; } - if (H323_ExternalRTPChannel::OnReceivedAckPDU( param )) { - GetRemoteAddress(remoteIpAddress, remotePort); + if (H323_ExternalRTPChannel::OnReceivedAckPDU(param)) { + H323_ExternalRTPChannel::GetRemoteAddress(remoteIpAddress, remotePort); if (h323debug) { cout << " -- remoteIpAddress: " << remoteIpAddress << endl; cout << " -- remotePort: " << remotePort << endl; @@ -838,7 +857,8 @@ void h323_callback_register(setup_incoming_cb ifunc, on_connection_cb confunc, start_logchan_cb lfunc, clear_con_cb clfunc, - con_established_cb efunc, + chan_ringing_cb rfunc, + con_established_cb efunc, send_digit_cb dfunc) { on_incoming_call = ifunc; @@ -846,6 +866,7 @@ void h323_callback_register(setup_incoming_cb ifunc, 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; } @@ -1085,7 +1106,7 @@ int h323_make_call(char *host, call_details_t *cd, call_options_t call_options) 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; @@ -1101,6 +1122,45 @@ int h323_clear_call(const char *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) { + 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) { + 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 */ int h323_answering_call(const char *token, int busy) diff --git a/channels/h323/ast_h323.h b/channels/h323/ast_h323.h index 91ebab0ae..966edabe8 100755 --- a/channels/h323/ast_h323.h +++ b/channels/h323/ast_h323.h @@ -198,7 +198,7 @@ class MyH323EndPoint : public H323EndPoint { public: - int MakeCall(const PString &, PString &, unsigned int *, unsigned int, char *); + int MakeCall(const PString &, PString &, unsigned int *, unsigned int, char *, char *s); BOOL ClearCall(const PString &); void OnClosedLogicalChannel(H323Connection &, const H323Channel &); @@ -225,8 +225,10 @@ class MyH323Connection : public H323Connection { MyH323Connection(MyH323EndPoint &, unsigned, unsigned); ~MyH323Connection(); - H323Channel * CreateRealTimeLogicalChannel(const H323Capability &, H323Channel::Directions, unsigned, - const H245_H2250LogicalChannelParameters *); + 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 &); @@ -245,33 +247,53 @@ class MyH323Connection : public H323Connection { PString sourceE164; PString destE164; - PIPSocket::Address externalIpAddress; // IP address of media server - PIPSocket::Address remoteIpAddress; // IP Address of remote endpoint - WORD externalPort; // local media server Data port (control is dataPort+1) - WORD remotePort; // remote endpoint Data port (control is dataPort+1) - WORD sessionId; - BOOL bridging; // Used to help determine which IP to use + PIPSocket::Address externalIpAddress; + PIPSocket::Address remoteIpAddress; + WORD externalPort; + WORD remotePort; + WORD sessionId; + BOOL bridging; }; class MyH323_ExternalRTPChannel : public H323_ExternalRTPChannel { - PCLASSINFO(MyH323_ExternalRTPChannel, H323_ExternalRTPChannel); - - public: - - MyH323_ExternalRTPChannel(MyH323Connection &, const H323Capability &, Directions, - unsigned, const PIPSocket::Address &, WORD); - + PCLASSINFO(MyH323_ExternalRTPChannel, H323_ExternalRTPChannel); + + public: + MyH323_ExternalRTPChannel( + MyH323Connection & connection, + const H323Capability & capability, + Directions direction, + unsigned sessionID); + + MyH323_ExternalRTPChannel( + MyH323Connection & connection, + const H323Capability & capability, + Directions direction, + unsigned sessionID, + const H323TransportAddress & data, + const H323TransportAddress & control); + + /* Create a new channel. */ + MyH323_ExternalRTPChannel( + MyH323Connection & connection, + const H323Capability & capability, + Directions direction, + unsigned sessionID, + const PIPSocket::Address & ip, + WORD dataPort); + + /* Destructor */ ~MyH323_ExternalRTPChannel(); - BOOL OnReceivedPDU( - const H245_H2250LogicalChannelParameters & param, /// Acknowledgement PDU - unsigned & errorCode /// Error on failure - ); - - BOOL OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param); + + BOOL OnReceivedAckPDU(const H245_H2250LogicalChannelAckParameters & param); -}; + PIPSocket::Address externalIpAddress; + PIPSocket::Address remoteIpAddress; + WORD externalPort; + WORD remotePort; +}; /** * The MyProcess is a necessary descendant PProcess class so that the H323EndPoint diff --git a/channels/h323/chan_h323.h b/channels/h323/chan_h323.h index 959d79d76..198247cc0 100755 --- a/channels/h323/chan_h323.h +++ b/channels/h323/chan_h323.h @@ -85,10 +85,11 @@ struct oh323_alias { PBX application and passed through make_call function*/ typedef struct call_options { - char *callerid; - int noFastStart; - int noH245Tunnelling; - int noSilenceSuppression; + char *callerid; + char *callername; + int noFastStart; + int noH245Tunnelling; + int noSilenceSuppression; unsigned int port; } call_options_t; @@ -101,6 +102,7 @@ typedef struct call_details { const char *call_token; const char *call_source_aliases; const char *call_dest_alias; + const char *call_source_name; const char *call_source_e164; const char *call_dest_e164; const char *sourceIp; @@ -136,6 +138,11 @@ setup_outbound_cb on_outgoing_call; 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); @@ -164,13 +171,14 @@ 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, + on_connection_cb, + start_logchan_cb, + clear_con_cb, + chan_ringing_cb, + con_established_cb, + send_digit_cb); int h323_set_capability(int, int); @@ -191,9 +199,13 @@ extern "C" { /* H323 create and destroy sessions */ int h323_make_call(char *host, call_details_t *cd, call_options_t); int h323_clear_call(const char *); + + /* H.323 alerting and progress */ + 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); - + int h323_soft_hangup(const char *data); int h323_show_codec(int fd, int argc, char *argv[]); -- cgit v1.2.3