Applied patch to fix some race conditions on call termination, thanks Peter Olsson

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13014 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Robert Joly 2009-04-14 07:10:55 +00:00
parent d5bf92f159
commit 59b3cdc2a6
2 changed files with 159 additions and 73 deletions

View File

@ -510,7 +510,20 @@ bool FSEndPoint::OnIncomingCall(OpalLocalConnection & connection)
OpalLocalConnection *FSEndPoint::CreateConnection(OpalCall & call, void *userData)
{
return new FSConnection(call, *this, (switch_caller_profile_t *)userData);
FSManager & mgr = (FSManager &) GetManager();
switch_core_session_t *fsSession = switch_core_session_request(mgr.GetSwitchInterface(),
(switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, NULL);
if (fsSession == NULL)
return NULL;
switch_channel_t *fsChannel = switch_core_session_get_channel(fsSession);
if (fsChannel == NULL) {
switch_core_session_destroy(&fsSession);
return NULL;
}
return new FSConnection(call, *this, (switch_caller_profile_t *)userData, fsSession, fsChannel);
}
@ -543,15 +556,13 @@ PBoolean FSCall::OnSetUp(OpalConnection & connection)
///////////////////////////////////////////////////////////////////////
FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, switch_caller_profile_t *outbound_profile)
FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, switch_caller_profile_t *outbound_profile, switch_core_session_t *fsSession, switch_channel_t *fsChannel)
: OpalLocalConnection(call, endpoint, NULL)
, m_endpoint(endpoint)
, m_fsSession(fsSession)
, m_fsChannel(fsChannel)
{
opal_private_t *tech_pvt;
FSManager & mgr = (FSManager &) endpoint.GetManager();
m_fsSession = switch_core_session_request(mgr.GetSwitchInterface(),
outbound_profile ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, NULL);
m_fsChannel = switch_core_session_get_channel(m_fsSession);
tech_pvt = (opal_private_t *) switch_core_session_alloc(m_fsSession, sizeof(*tech_pvt));
tech_pvt->me = this;
@ -679,8 +690,7 @@ void FSConnection::OnEstablished()
PBoolean FSConnection::SendUserInputTone(char tone, unsigned duration)
{
switch_dtmf_t dtmf = { tone, duration };
return (switch_channel_queue_dtmf(m_fsChannel, &dtmf) == SWITCH_STATUS_SUCCESS) ? true : false;
return switch_channel_queue_dtmf(m_fsChannel, &dtmf) == SWITCH_STATUS_SUCCESS;
}
OpalMediaFormatList FSConnection::GetMediaFormats() const
@ -974,6 +984,14 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg
OnAlerting();
break;
case SWITCH_MESSAGE_INDICATE_DEFLECT:
{
char transfer_to[128] = "";
switch_set_string(transfer_to, msg->string_arg);
TransferConnection(transfer_to);
break;
}
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
{
@ -1163,6 +1181,7 @@ PBoolean FSMediaStream::Open()
m_switchCodec->implementation->samples_per_packet,
switch_core_session_get_pool(m_fsSession)) != SWITCH_STATUS_SUCCESS) {
switch_core_codec_destroy(m_switchCodec);
m_switchCodec = NULL;
return false;
}
} else {
@ -1190,6 +1209,11 @@ PBoolean FSMediaStream::Close()
if (!IsOpen())
return false;
/* forget these FS will properly destroy them for us */
m_switchTimer = NULL;
m_switchCodec = NULL;
return OpalMediaStream::Close();
}
@ -1205,6 +1229,21 @@ PBoolean FSMediaStream::RequiresPatchThread(OpalMediaStream *) const
return false;
}
bool FSMediaStream::CheckPatchAndLock()
{
if (GetConnection().GetPhase() >= GetConnection().ReleasingPhase || !IsOpen())
return false;
if (LockReadWrite()) {
if (!GetPatch() || !IsOpen()) {
UnlockReadWrite();
return false;
}
return true;
} else {
return false;
}
}
switch_status_t FSMediaStream::read_frame(switch_frame_t **frame, switch_io_flag_t flags)
{
@ -1222,15 +1261,26 @@ switch_status_t FSMediaStream::read_frame(switch_frame_t **frame, switch_io_flag
while(!GetPatch()) {
switch_cond_next();
}
if (CheckPatchAndLock()) {
GetPatch()->OnPatchStart();
m_callOnStart = false;
UnlockReadWrite();
} else {
return SWITCH_STATUS_FALSE;
}
}
m_readFrame.flags = 0;
/*
while (switch_channel_ready(m_fsChannel)) {
if (CheckPatchAndLock()) {
if (!GetPatch()->GetSource().ReadPacket(m_readRTP)) {
UnlockReadWrite();
return SWITCH_STATUS_FALSE;
}
UnlockReadWrite();
} else {
return SWITCH_STATUS_FALSE;
}
@ -1249,9 +1299,16 @@ switch_status_t FSMediaStream::read_frame(switch_frame_t **frame, switch_io_flag
if (switch_channel_test_private_flag(m_fsChannel, CF_NEED_FLUSH)) {
switch_channel_clear_private_flag(m_fsChannel, CF_NEED_FLUSH);
for(;;) {
if (CheckPatchAndLock()) {
if (!GetPatch()->GetSource().ReadPacket(m_readRTP)) {
UnlockReadWrite();
return SWITCH_STATUS_FALSE;
}
UnlockReadWrite();
} else {
return SWITCH_STATUS_FALSE;
}
if (!m_readRTP.GetPayloadSize()) {
m_readFrame.flags = SFF_CNG;
break;
@ -1259,7 +1316,13 @@ switch_status_t FSMediaStream::read_frame(switch_frame_t **frame, switch_io_flag
}
} else {
if (CheckPatchAndLock()) {
if (!m_switchTimer || !GetPatch()->GetSource().ReadPacket(m_readRTP)) {
UnlockReadWrite();
return SWITCH_STATUS_FALSE;
}
UnlockReadWrite();
} else {
return SWITCH_STATUS_FALSE;
}
@ -1303,8 +1366,13 @@ switch_status_t FSMediaStream::write_frame(const switch_frame_t *frame, switch_i
}
if (m_callOnStart) {
if (CheckPatchAndLock()) {
GetPatch()->OnPatchStart();
m_callOnStart = false;
UnlockReadWrite();
} else {
return SWITCH_STATUS_FALSE;
}
}
if ((frame->flags & SFF_CNG)) {
@ -1313,9 +1381,16 @@ switch_status_t FSMediaStream::write_frame(const switch_frame_t *frame, switch_i
if ((frame->flags & SFF_RAW_RTP) != 0) {
RTP_DataFrame rtp((const BYTE *) frame->packet, frame->packetlen, false);
if (CheckPatchAndLock()) {
if (GetPatch()->PushFrame(rtp)) {
UnlockReadWrite();
return SWITCH_STATUS_SUCCESS;
}
UnlockReadWrite();
} else {
return SWITCH_STATUS_FALSE;
}
}
/* If we reach this code it means a call to an ivr or something else that does not generate timestamps
@ -1337,9 +1412,15 @@ switch_status_t FSMediaStream::write_frame(const switch_frame_t *frame, switch_i
memcpy(rtp.GetPayloadPtr(), frame->data, frame->datalen);
if (CheckPatchAndLock()) {
if (GetPatch()->PushFrame(rtp)) {
UnlockReadWrite();
return SWITCH_STATUS_SUCCESS;
}
UnlockReadWrite();
} else {
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_FALSE;

View File

@ -177,7 +177,11 @@ class FSConnection:public OpalLocalConnection {
PCLASSINFO(FSConnection, OpalLocalConnection)
public:
FSConnection(OpalCall & call, FSEndPoint & endpoint, switch_caller_profile_t *outbound_profile);
FSConnection(OpalCall & call,
FSEndPoint & endpoint,
switch_caller_profile_t *outbound_profile,
switch_core_session_t *fsSession,
switch_channel_t *fsChannel);
virtual bool OnIncoming();
virtual void OnReleased();
@ -194,7 +198,6 @@ class FSConnection:public OpalLocalConnection {
DECLARE_CALLBACK0(on_init);
DECLARE_CALLBACK0(on_routing);
DECLARE_CALLBACK0(on_execute);
//DECLARE_CALLBACK0(on_hangup);
DECLARE_CALLBACK0(on_exchange_media);
DECLARE_CALLBACK0(on_soft_execute);
@ -251,6 +254,8 @@ class FSMediaStream:public OpalMediaStream {
RTP_DataFrame m_readRTP;
bool m_callOnStart;
uint32_t m_timeStamp;
bool CheckPatchAndLock();
};