*** empty log message ***
git-svn-id: http://voip.null.ro/svn/yate@946 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
e8cc8b0fe3
commit
4b85afa41c
|
@ -423,9 +423,11 @@ bool IAXEngine::acceptFormatAndCapability(IAXTransaction* trans)
|
|||
return false;
|
||||
}
|
||||
trans->m_format = format;
|
||||
trans->m_formatIn = format;
|
||||
trans->m_formatOut = format;
|
||||
trans->m_capability = capability;
|
||||
if (trans->outgoing())
|
||||
trans->m_formatIn = format;
|
||||
else
|
||||
trans->m_formatOut = format;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -494,7 +496,7 @@ bool IAXEngine::isMD5ChallengeCorrect(const String& md5data, const String& chall
|
|||
/*
|
||||
* IAXEvent
|
||||
*/
|
||||
IAXEvent::IAXEvent(Type type, bool local, bool final, IAXTransaction* transaction, u_int8_t frameType, u_int8_t subclass)
|
||||
IAXEvent::IAXEvent(Type type, bool local, bool final, IAXTransaction* transaction, u_int8_t frameType, u_int32_t subclass)
|
||||
: m_type(type), m_frameType(frameType), m_subClass(subclass), m_local(local), m_final(final), m_transaction(0)
|
||||
|
||||
{
|
||||
|
|
|
@ -365,17 +365,20 @@ IAXEvent* IAXTransaction::getEvent(u_int64_t time)
|
|||
// Process outgoing frames
|
||||
ListIterator lout(m_outFrames);
|
||||
IAXFrameOut* lastFrameAck = 0;
|
||||
delFrame = false;
|
||||
for (; (obj = lout.get());) {
|
||||
IAXFrameOut* frame = static_cast<IAXFrameOut*>(obj);
|
||||
ev = getEventResponse(frame,delFrame);
|
||||
if (delFrame)
|
||||
// Frame received ACK or other response ?
|
||||
if (frame->ack() || delFrame) {
|
||||
frame->setAck();
|
||||
if(frame->ack())
|
||||
lastFrameAck = frame;
|
||||
if (ev)
|
||||
break;
|
||||
if(frame->ack() && frame->ackOnly())
|
||||
continue;
|
||||
// Frame received non ACK response
|
||||
if (ev || delFrame)
|
||||
break;
|
||||
if (frame->ackOnly())
|
||||
continue;
|
||||
}
|
||||
// Adjust timeout for acknoledged auth frames sent with no auth response
|
||||
if (state() == NewRemoteInvite_AuthSent && frame->ack())
|
||||
frame->adjustAuthTimeout(time + m_engine->authTimeout() * 1000);
|
||||
|
@ -406,10 +409,12 @@ IAXEvent* IAXTransaction::getEvent(u_int64_t time)
|
|||
for (; (obj = lout.get());) {
|
||||
IAXFrameOut* frame = static_cast<IAXFrameOut*>(obj);
|
||||
if (frame == lastFrameAck) {
|
||||
DDebug(m_engine,DebugAll,"Transaction(%u,%u) removing outgoing frame(%u,%u) oseq=%u iseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->oSeqNo(),
|
||||
frame->iSeqNo(),frame->timeStamp(),this);
|
||||
m_outFrames.remove(frame,true);
|
||||
if (ev || delFrame || frame->ackOnly()) {
|
||||
DDebug(m_engine,DebugAll,"Transaction(%u,%u) removing outgoing frame(%u,%u) oseq=%u iseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->oSeqNo(),
|
||||
frame->iSeqNo(),frame->timeStamp(),this);
|
||||
m_outFrames.remove(frame,true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
frame->setAck();
|
||||
|
@ -420,13 +425,16 @@ IAXEvent* IAXTransaction::getEvent(u_int64_t time)
|
|||
m_outFrames.remove(frame,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev)
|
||||
return keepEvent(ev);
|
||||
// Process incoming frames
|
||||
ListIterator lin(m_inFrames);
|
||||
for (; (obj = lin.get());) {
|
||||
IAXFullFrame* frame = static_cast<IAXFullFrame*>(obj);
|
||||
// If frame is ACK, ignore it
|
||||
if (frame->type() == IAXFrame::IAX && frame->subclass() == IAXControl::Ack)
|
||||
continue;
|
||||
DDebug(m_engine,DebugAll,"Transaction(%u,%u) dequeued Frame(%u,%u) iseq=%u oseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),frame->iSeqNo(),frame->oSeqNo(),frame->timeStamp(),this);
|
||||
if (m_state == IAXTransaction::Unknown)
|
||||
|
@ -669,14 +677,14 @@ void IAXTransaction::print()
|
|||
for(i = 0, l = m_outFrames.skipNull(); l; l = l->next(), i++) {
|
||||
IAXFrameOut* frame = static_cast<IAXFrameOut*>(l->get());
|
||||
if (frame)
|
||||
Output(" %5u Type: %3u Subclass: %3u Out: %5u In: %5u Timestamp: %5u Ack: %u AckOnly: %u",
|
||||
Output(" %5u Type: %-3u Subclass: %-3u Out: %-5u In: %-5u Timestamp: %-5u Ack: %u AckOnly: %u",
|
||||
i+1,frame->type(),frame->subclass(),frame->oSeqNo(),frame->iSeqNo(), frame->timeStamp(),frame->ack(),frame->ackOnly());
|
||||
}
|
||||
Output("Incoming: %u",m_inFrames.count());
|
||||
for(i = 0, l = m_inFrames.skipNull(); l; l = l->next(), i++) {
|
||||
IAXFullFrame* frame = static_cast<IAXFrameOut*>(l->get());
|
||||
if (frame)
|
||||
Output(" %5u Type: %3u Subclass: %3u Out: %5u In: %5u Timestamp: %5u",
|
||||
Output(" %5u Type: %-3u Subclass: %-3u Out: %-5u In: %-5u Timestamp: %-5u",
|
||||
i+1,frame->type(),frame->subclass(),frame->oSeqNo(),frame->iSeqNo(), frame->timeStamp());
|
||||
}
|
||||
Debug(m_engine,DebugInfo,"Transaction - END PRINT [%p]",this);
|
||||
|
@ -694,7 +702,10 @@ void IAXTransaction::init(IAXIEList& ieList)
|
|||
ieList.getString(IAXInfoElement::CALLED_CONTEXT,m_calledContext);
|
||||
ieList.getNumeric(IAXInfoElement::FORMAT,m_format);
|
||||
ieList.getNumeric(IAXInfoElement::CAPABILITY,m_capability);
|
||||
m_formatIn = m_formatOut = m_format;
|
||||
if (outgoing())
|
||||
m_formatOut = m_format;
|
||||
else
|
||||
m_formatIn = m_format;
|
||||
break;
|
||||
case RegReq:
|
||||
case RegRel:
|
||||
|
@ -880,11 +891,9 @@ IAXEvent* IAXTransaction::getEventResponse(IAXFrameOut* frame, bool& delFrame)
|
|||
return 0;
|
||||
}
|
||||
// Frame only need ACK. Didn't found it. Return
|
||||
delFrame = true;
|
||||
if (frame->ackOnly()) {
|
||||
delFrame = false;
|
||||
if (frame->ackOnly())
|
||||
return 0;
|
||||
}
|
||||
delFrame = true;
|
||||
switch (type()) {
|
||||
case New:
|
||||
return getEventResponse_New(frame,delFrame);
|
||||
|
@ -901,7 +910,8 @@ IAXEvent* IAXTransaction::getEventResponse(IAXFrameOut* frame, bool& delFrame)
|
|||
default: ;
|
||||
}
|
||||
delFrame = false;
|
||||
return 0;
|
||||
// Internal stuff
|
||||
return processInternalOutgoingRequest(frame,delFrame);
|
||||
}
|
||||
|
||||
IAXEvent* IAXTransaction::getEventResponse_New(IAXFrameOut* frame, bool& delFrame)
|
||||
|
@ -917,8 +927,8 @@ IAXEvent* IAXTransaction::getEventResponse_New(IAXFrameOut* frame, bool& delFram
|
|||
// Frame is NEW: AUTHREQ, ACCEPT, REJECT, HANGUP ?
|
||||
if (0 != (ev = createResponse(frame,IAXFrame::IAX,IAXControl::AuthReq,IAXEvent::AuthReq,false,NewLocalInvite_AuthRecv)))
|
||||
return processAuthReq(ev);
|
||||
if (0 != (ev = createResponse(frame,IAXFrame::IAX,IAXControl::Accept,IAXEvent::Accept,false,Connected)))
|
||||
return ev;
|
||||
if (0 != (ev = createResponse(frame,IAXFrame::IAX,IAXControl::Accept,IAXEvent::Accept,false,Connected)))
|
||||
return processAccept(ev);
|
||||
if (0 != (ev = createResponse(frame,IAXFrame::IAX,IAXControl::Reject,IAXEvent::Reject,false,Terminating)))
|
||||
return ev;
|
||||
if (0 != (ev = createResponse(frame,IAXFrame::IAX,IAXControl::Hangup,IAXEvent::Hangup,false,Terminating)))
|
||||
|
@ -929,7 +939,7 @@ IAXEvent* IAXTransaction::getEventResponse_New(IAXFrameOut* frame, bool& delFram
|
|||
break;
|
||||
// Frame is AUTHREP: ACCEPT, REJECT, HANGUP ?
|
||||
if (0 != (ev = createResponse(frame,IAXFrame::IAX,IAXControl::Accept,IAXEvent::Accept,false,Connected)))
|
||||
return ev;
|
||||
return processAccept(ev);
|
||||
if (0 != (ev = createResponse(frame,IAXFrame::IAX,IAXControl::Reject,IAXEvent::Reject,false,Terminating)))
|
||||
return ev;
|
||||
if (0 != (ev = createResponse(frame,IAXFrame::IAX,IAXControl::Hangup,IAXEvent::Hangup,false,Terminating)))
|
||||
|
@ -955,43 +965,51 @@ IAXEvent* IAXTransaction::getEventResponse_New(IAXFrameOut* frame, bool& delFram
|
|||
|
||||
IAXEvent* IAXTransaction::processAuthReq(IAXEvent* event)
|
||||
{
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u). AuthReq received",localCallNo(),remoteCallNo());
|
||||
if (event->type() == IAXEvent::Invalid)
|
||||
if (event->type() != IAXEvent::AuthReq)
|
||||
return event;
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u). AuthReq received",localCallNo(),remoteCallNo());
|
||||
// Valid authmethod & challenge ?
|
||||
u_int32_t authmethod;
|
||||
bool bAuthMethod = event->getList().getNumeric(IAXInfoElement::AUTHMETHODS,authmethod) && (authmethod & m_authmethod);
|
||||
bool bChallenge = event->getList().getString(IAXInfoElement::CHALLENGE,m_challenge);
|
||||
IAXEvent* retEv;
|
||||
if (bAuthMethod && bChallenge) {
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u). Internal authentication reply",localCallNo(),remoteCallNo());
|
||||
sendAuthReply();
|
||||
retEv = event;
|
||||
return event;
|
||||
}
|
||||
else {
|
||||
delete event;
|
||||
retEv = internalReject(s_iax_modNoAuthMethod);
|
||||
}
|
||||
return retEv;
|
||||
delete event;
|
||||
return internalReject(s_iax_modNoAuthMethod);
|
||||
}
|
||||
|
||||
IAXEvent* IAXTransaction::processAccept(IAXEvent* event)
|
||||
{
|
||||
if (event->type() != IAXEvent::Accept)
|
||||
return event;
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u). Accept received",localCallNo(),remoteCallNo());
|
||||
// We might have a format received with a Voice frame
|
||||
if (m_formatIn)
|
||||
return event;
|
||||
m_format = 0;
|
||||
event->getList().getNumeric(IAXInfoElement::FORMAT,m_format);
|
||||
if (m_engine->acceptFormatAndCapability(this))
|
||||
return event;
|
||||
delete event;
|
||||
return internalReject(s_iax_modNoMediaFormat);
|
||||
}
|
||||
|
||||
IAXEvent* IAXTransaction::processAuthRep(IAXEvent* event)
|
||||
{
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u). Auth Reply received",localCallNo(),remoteCallNo());
|
||||
if (event->type() == IAXEvent::Invalid)
|
||||
if (event->type() != IAXEvent::AuthRep)
|
||||
return event;
|
||||
Debug(m_engine,DebugAll,"Transaction(%u,%u). Auth Reply received",localCallNo(),remoteCallNo());
|
||||
event->getList().getString(IAXInfoElement::MD5_RESULT,m_authdata);
|
||||
IAXEvent* retEv;
|
||||
if (type() == RegReq || type() == RegRel) {
|
||||
if (!IAXEngine::isMD5ChallengeCorrect(m_authdata,m_challenge,m_password))
|
||||
retEv = internalReject(s_iax_modInvalidAuth);
|
||||
else
|
||||
retEv = internalAccept();
|
||||
delete event;
|
||||
if (!IAXEngine::isMD5ChallengeCorrect(m_authdata,m_challenge,m_password))
|
||||
return internalReject(s_iax_modInvalidAuth);
|
||||
return internalAccept();
|
||||
}
|
||||
else
|
||||
retEv = event;
|
||||
return retEv;
|
||||
return event;
|
||||
}
|
||||
|
||||
IAXEvent* IAXTransaction::getEventResponse_Reg(IAXFrameOut* frame, bool& delFrame)
|
||||
|
@ -1257,6 +1275,12 @@ void IAXTransaction::sendVNAK()
|
|||
m_engine->writeSocket(buf,sizeof(buf),remoteAddr());
|
||||
}
|
||||
|
||||
void IAXTransaction::sendUnsupport(u_int32_t subclass)
|
||||
{
|
||||
unsigned char d[3] = {IAXInfoElement::IAX_UNKNOWN,1,IAXFrame::packSubclass(subclass)};
|
||||
postFrame(IAXFrame::IAX,IAXControl::Unsupport,d,sizeof(d),0,true);
|
||||
}
|
||||
|
||||
IAXEvent* IAXTransaction::processInternalOutgoingRequest(IAXFrameOut* frame, bool& delFrame)
|
||||
{
|
||||
delFrame = false;
|
||||
|
@ -1349,7 +1373,7 @@ IAXEvent* IAXTransaction::processMidCallIAXControl(const IAXFullFrame* frame, bo
|
|||
return 0;
|
||||
case IAXControl::Transfer:
|
||||
case IAXControl::TxReady:
|
||||
postFrame(IAXFrame::IAX,IAXControl::Unsupport,0,0,0,true);
|
||||
sendUnsupport(frame->subclass());
|
||||
return createEvent(IAXEvent::NotImplemented,false,frame,Terminating);
|
||||
case IAXControl::DpReq:
|
||||
case IAXControl::DpRep:
|
||||
|
@ -1362,7 +1386,7 @@ IAXEvent* IAXTransaction::processMidCallIAXControl(const IAXFullFrame* frame, bo
|
|||
case IAXControl::MWI:
|
||||
case IAXControl::Provision:
|
||||
case IAXControl::FwData:
|
||||
//postFrame(IAXFrame::IAX,IAXControl::Unsupport,0,0,0,true);
|
||||
sendUnsupport(frame->subclass());
|
||||
return createEvent(IAXEvent::NotImplemented,false,frame,state());
|
||||
default: ;
|
||||
}
|
||||
|
@ -1405,15 +1429,25 @@ IAXTransaction* IAXTransaction::processVoiceFrame(const IAXFullFrame* frame)
|
|||
// Process format
|
||||
DDebug(m_engine,DebugAll,"Transaction(%u,%u). Received Voice Frame(%u,%u) iseq=%u oseq=%u stamp=%u [%p]",
|
||||
localCallNo(),remoteCallNo(),frame->type(),frame->subclass(),
|
||||
frame->fullFrame()->iSeqNo(),frame->fullFrame()->oSeqNo(),frame->timeStamp(),this);
|
||||
frame->iSeqNo(),frame->oSeqNo(),frame->timeStamp(),this);
|
||||
sendAck(frame);
|
||||
if (frame->fullFrame()->subclass() && frame->fullFrame()->subclass() != m_formatIn) {
|
||||
// Format changed.
|
||||
if (m_engine->voiceFormatChanged(this,frame->fullFrame()->subclass()))
|
||||
m_formatIn = frame->fullFrame()->subclass();
|
||||
else {
|
||||
DDebug(m_engine,DebugAll,"IAXTransaction(%u,%u). Process Voice Frame. Media format (%u) change rejected!",
|
||||
localCallNo(),remoteCallNo(),m_format);
|
||||
// We might have an incoming media format received with an Accept frame
|
||||
if (m_formatIn) {
|
||||
if (frame->subclass() && frame->subclass() != m_formatIn) {
|
||||
// Format changed.
|
||||
if (m_engine->voiceFormatChanged(this,frame->fullFrame()->subclass()))
|
||||
m_formatIn = frame->fullFrame()->subclass();
|
||||
else {
|
||||
DDebug(m_engine,DebugAll,"IAXTransaction(%u,%u). Process Voice Frame. Media format (%u) change rejected!",
|
||||
localCallNo(),remoteCallNo(),m_format);
|
||||
m_pendingEvent = internalReject(s_iax_modNoMediaFormat);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_format = frame->subclass();
|
||||
if (!m_engine->acceptFormatAndCapability(this)) {
|
||||
m_pendingEvent = internalReject(s_iax_modNoMediaFormat);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1506,14 +1506,22 @@ protected:
|
|||
/**
|
||||
* Process an authentication request. If valid, send an authentication reply
|
||||
* @param event Already generated event
|
||||
* @return Pointer to an IAXEvent or 0
|
||||
* @return Pointer to a valid IAXEvent
|
||||
*/
|
||||
IAXEvent* IAXTransaction::processAuthReq(IAXEvent* event);
|
||||
|
||||
/**
|
||||
* Process an accept. If not valid (call m_engine->acceptFormatAndCapability) send a reject.
|
||||
* Otherwise return the event
|
||||
* @param event Already generated event
|
||||
* @return Pointer to a valid IAXEvent
|
||||
*/
|
||||
IAXEvent* IAXTransaction::processAccept(IAXEvent* event);
|
||||
|
||||
/**
|
||||
* Process an authentication reply
|
||||
* @param event Already generated event
|
||||
* @return Pointer to an IAXEvent or 0
|
||||
* @return Pointer to a valid IAXEvent
|
||||
*/
|
||||
IAXEvent* IAXTransaction::processAuthRep(IAXEvent* event);
|
||||
|
||||
|
@ -1610,6 +1618,12 @@ protected:
|
|||
*/
|
||||
void sendVNAK();
|
||||
|
||||
/**
|
||||
* Send an Unsupport frame
|
||||
* @param subclass Unsupported frame's subclass
|
||||
*/
|
||||
void sendUnsupport(u_int32_t subclass);
|
||||
|
||||
/**
|
||||
* Internal protocol outgoing frames processing (PING/LAGRQ)
|
||||
* @param frame Frame to process
|
||||
|
@ -1839,7 +1853,7 @@ public:
|
|||
* Get the subclass of the frame that generated the event
|
||||
* @return Frame subclass
|
||||
*/
|
||||
inline u_int8_t subclass()
|
||||
inline u_int32_t subclass()
|
||||
{ return m_subClass; }
|
||||
|
||||
/**
|
||||
|
@ -1880,7 +1894,7 @@ protected:
|
|||
* @param frameType The type of the frame that generated the event
|
||||
* @param subclass The subclass of the frame that generated the event
|
||||
*/
|
||||
IAXEvent(Type type, bool local, bool final, IAXTransaction* transaction, u_int8_t frameType = 0, u_int8_t subclass = 0);
|
||||
IAXEvent(Type type, bool local, bool final, IAXTransaction* transaction, u_int8_t frameType = 0, u_int32_t subclass = 0);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -1897,7 +1911,7 @@ private:
|
|||
|
||||
Type m_type; // Event type
|
||||
u_int8_t m_frameType; // Frame type
|
||||
u_int8_t m_subClass; // Frame subclass
|
||||
u_int32_t m_subClass; // Frame subclass
|
||||
bool m_local; // If true the event is generated locally, the receiver MUST not respond
|
||||
bool m_final; // Final event flag
|
||||
IAXTransaction* m_transaction; // Transaction that generated this event
|
||||
|
|
Loading…
Reference in New Issue