173 |
case SentUpdateGlare: |
case SentUpdateGlare: |
174 |
case SentReinvite: |
case SentReinvite: |
175 |
case SentReinviteGlare: |
case SentReinviteGlare: |
176 |
|
case SentReinviteNoOffer: |
177 |
|
case SentReinviteAnswered: |
178 |
|
case SentReinviteNoOfferGlare: |
179 |
case ReceivedUpdate: |
case ReceivedUpdate: |
180 |
case ReceivedReinvite: |
case ReceivedReinvite: |
181 |
case ReceivedReinviteNoOffer: |
case ReceivedReinviteNoOffer: |
193 |
{ |
{ |
194 |
switch (mState) |
switch (mState) |
195 |
{ |
{ |
|
case UAC_Start: |
|
196 |
case UAC_Early: |
case UAC_Early: |
197 |
case UAC_EarlyWithOffer: |
case UAC_EarlyWithOffer: |
198 |
case UAC_EarlyWithAnswer: |
case UAC_EarlyWithAnswer: |
|
|
|
|
//case UAC_Answered: |
|
|
//case UAC_Terminated: |
|
199 |
case UAC_SentUpdateEarly: |
case UAC_SentUpdateEarly: |
|
case UAC_SentUpdateConnected: |
|
200 |
case UAC_ReceivedUpdateEarly: |
case UAC_ReceivedUpdateEarly: |
201 |
//case UAC_SentAnswer: |
case UAC_SentAnswer: |
202 |
case UAC_QueuedUpdate: |
case UAC_QueuedUpdate: |
203 |
|
return true; |
204 |
|
default: |
205 |
|
return false; |
206 |
|
} |
207 |
|
} |
208 |
|
|
209 |
|
bool |
210 |
|
InviteSession::isAccepted() const |
211 |
|
{ |
212 |
|
switch (mState) |
213 |
|
{ |
214 |
case UAS_Start: |
case UAS_Start: |
215 |
case UAS_Offer: |
case UAS_Offer: |
216 |
case UAS_OfferProvidedAnswer: |
case UAS_OfferProvidedAnswer: |
217 |
case UAS_EarlyOffer: |
case UAS_EarlyOffer: |
218 |
|
case UAS_EarlyProvidedOffer: |
219 |
case UAS_EarlyProvidedAnswer: |
case UAS_EarlyProvidedAnswer: |
220 |
case UAS_EarlyNoOffer: |
case UAS_EarlyNoOffer: |
221 |
case UAS_FirstEarlyReliable: |
case UAS_FirstEarlyReliable: |
222 |
|
case UAS_FirstSentOfferReliable: |
223 |
case UAS_EarlyReliable: |
case UAS_EarlyReliable: |
224 |
return true; |
return true; |
|
|
|
225 |
default: |
default: |
226 |
return false; |
return false; |
227 |
} |
} |
228 |
} |
} |
229 |
|
|
|
|
|
230 |
bool |
bool |
231 |
InviteSession::isTerminated() const |
InviteSession::isTerminated() const |
232 |
{ |
{ |
255 |
} |
} |
256 |
|
|
257 |
void |
void |
258 |
|
InviteSession::requestOffer() |
259 |
|
{ |
260 |
|
switch (mState) |
261 |
|
{ |
262 |
|
case Connected: |
263 |
|
case WaitingToRequestOffer: |
264 |
|
transition(SentReinviteNoOffer); |
265 |
|
mDialog.makeRequest(mLastSessionModification, INVITE); |
266 |
|
mLastSessionModification.remove(h_ProxyAuthorizations); // remove remote credentials. |
267 |
|
mLastSessionModification.setContents(0); // Clear the SDP contents from the INVITE |
268 |
|
setSessionTimerHeaders(mLastSessionModification); |
269 |
|
|
270 |
|
InfoLog (<< "Sending " << mLastSessionModification.brief()); |
271 |
|
// call send to give app an chance to adorn the message. |
272 |
|
send(mLastSessionModification); |
273 |
|
break; |
274 |
|
|
275 |
|
case Answered: |
276 |
|
// queue the offer to be sent after the ACK is received |
277 |
|
transition(WaitingToRequestOffer); |
278 |
|
break; |
279 |
|
|
280 |
|
// ?slg? Can we handle all of the states listed in isConnected() ??? |
281 |
|
default: |
282 |
|
WarningLog (<< "Can't requestOffer when not in Connected state"); |
283 |
|
throw DialogUsage::Exception("Can't request an offer", __FILE__,__LINE__); |
284 |
|
} |
285 |
|
} |
286 |
|
|
287 |
|
void |
288 |
InviteSession::provideOffer(const SdpContents& offer, |
InviteSession::provideOffer(const SdpContents& offer, |
289 |
DialogUsageManager::EncryptionLevel level, |
DialogUsageManager::EncryptionLevel level, |
290 |
const SdpContents* alternative) |
const SdpContents* alternative) |
385 |
break; |
break; |
386 |
} |
} |
387 |
|
|
388 |
|
case SentReinviteAnswered: |
389 |
|
transition(Connected); |
390 |
|
sendAck(&answer); |
391 |
|
|
392 |
|
mCurrentRemoteSdp = mProposedRemoteSdp; |
393 |
|
mCurrentLocalSdp = InviteSession::makeSdp(answer); |
394 |
|
break; |
395 |
|
|
396 |
default: |
default: |
397 |
WarningLog (<< "Can't provideAnswer when not in Connected state"); |
WarningLog (<< "Can't provideAnswer when not in Connected state"); |
398 |
throw DialogUsage::Exception("Can't provide an offer", __FILE__,__LINE__); |
throw DialogUsage::Exception("Can't provide an offer", __FILE__,__LINE__); |
421 |
case SentUpdate: |
case SentUpdate: |
422 |
case SentUpdateGlare: |
case SentUpdateGlare: |
423 |
case SentReinviteGlare: |
case SentReinviteGlare: |
424 |
|
case SentReinviteNoOfferGlare: |
425 |
|
case SentReinviteAnswered: |
426 |
{ |
{ |
427 |
// !jf! do we need to store the BYE somewhere? |
// !jf! do we need to store the BYE somewhere? |
428 |
sendBye(); |
sendBye(); |
432 |
} |
} |
433 |
|
|
434 |
case SentReinvite: |
case SentReinvite: |
435 |
|
case SentReinviteNoOffer: |
436 |
transition(WaitingToTerminate); |
transition(WaitingToTerminate); |
437 |
break; |
break; |
438 |
|
|
657 |
case SentReinvite: |
case SentReinvite: |
658 |
dispatchSentReinvite(msg); |
dispatchSentReinvite(msg); |
659 |
break; |
break; |
660 |
|
case SentReinviteNoOffer: |
661 |
|
dispatchSentReinviteNoOffer(msg); |
662 |
|
break; |
663 |
|
case SentReinviteAnswered: |
664 |
|
dispatchSentReinviteAnswered(msg); |
665 |
|
break; |
666 |
case SentUpdateGlare: |
case SentUpdateGlare: |
667 |
case SentReinviteGlare: |
case SentReinviteGlare: |
668 |
// The behavior is the same except for timer which is handled in dispatch(Timer) |
// The behavior is the same except for timer which is handled in dispatch(Timer) |
669 |
dispatchGlare(msg); |
dispatchGlare(msg); |
670 |
break; |
break; |
671 |
|
case SentReinviteNoOfferGlare: |
672 |
|
dispatchReinviteNoOfferGlare(msg); |
673 |
|
break; |
674 |
case ReceivedUpdate: |
case ReceivedUpdate: |
675 |
case ReceivedReinvite: |
case ReceivedReinvite: |
676 |
case ReceivedReinviteNoOffer: |
case ReceivedReinviteNoOffer: |
685 |
case WaitingToOffer: |
case WaitingToOffer: |
686 |
dispatchWaitingToOffer(msg); |
dispatchWaitingToOffer(msg); |
687 |
break; |
break; |
688 |
|
case WaitingToRequestOffer: |
689 |
|
dispatchWaitingToRequestOffer(msg); |
690 |
|
break; |
691 |
case WaitingToTerminate: |
case WaitingToTerminate: |
692 |
dispatchWaitingToTerminate(msg); |
dispatchWaitingToTerminate(msg); |
693 |
break; |
break; |
749 |
assert(mProposedLocalSdp.get()); |
assert(mProposedLocalSdp.get()); |
750 |
//!dcm! -- should this be onIllegalNegotiation? |
//!dcm! -- should this be onIllegalNegotiation? |
751 |
mDum.mInviteSessionHandler->onOfferRejected(getSessionHandle(), 0); |
mDum.mInviteSessionHandler->onOfferRejected(getSessionHandle(), 0); |
752 |
if (dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get())) |
provideProposedOffer(); |
|
{ |
|
|
provideOffer( *(dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().back())), |
|
|
mProposedEncryptionLevel, |
|
|
dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().front())); |
|
|
} |
|
|
else |
|
|
{ |
|
|
provideOffer(*(dynamic_cast<SdpContents*>(mProposedLocalSdp.get())), mProposedEncryptionLevel, 0); |
|
|
} |
|
753 |
} |
} |
754 |
} |
} |
755 |
} |
} |
769 |
InfoLog (<< "Retransmitting the reINVITE (glare condition timer)"); |
InfoLog (<< "Retransmitting the reINVITE (glare condition timer)"); |
770 |
send(mLastSessionModification); |
send(mLastSessionModification); |
771 |
} |
} |
772 |
|
else if (mState == SentReinviteNoOfferGlare) |
773 |
|
{ |
774 |
|
transition(SentReinviteNoOffer); |
775 |
|
|
776 |
|
InfoLog (<< "Retransmitting the reINVITE-nooffer (glare condition timer)"); |
777 |
|
send(mLastSessionModification); |
778 |
|
} |
779 |
} |
} |
780 |
else if (timeout.type() == DumTimeout::SessionExpiration) |
else if (timeout.type() == DumTimeout::SessionExpiration) |
781 |
{ |
{ |
822 |
mLastSessionModification = msg; |
mLastSessionModification = msg; |
823 |
transition(ReceivedReinvite); |
transition(ReceivedReinvite); |
824 |
mCurrentEncryptionLevel = getEncryptionLevel(msg); |
mCurrentEncryptionLevel = getEncryptionLevel(msg); |
825 |
|
mProposedRemoteSdp = InviteSession::makeSdp(*sdp); |
826 |
|
|
827 |
//handler->onDialogModified(getSessionHandle(), Offer, msg); |
//handler->onDialogModified(getSessionHandle(), Offer, msg); |
828 |
handler->onOffer(getSessionHandle(), msg, *sdp); |
handler->onOffer(getSessionHandle(), msg, *sdp); |
829 |
break; |
break; |
844 |
// See rfc3311 5.2, 4th paragraph. |
// See rfc3311 5.2, 4th paragraph. |
845 |
mLastSessionModification = msg; |
mLastSessionModification = msg; |
846 |
mCurrentEncryptionLevel = getEncryptionLevel(msg); |
mCurrentEncryptionLevel = getEncryptionLevel(msg); |
847 |
|
mProposedRemoteSdp = InviteSession::makeSdp(*sdp); |
848 |
handler->onOffer(getSessionHandle(), msg, *sdp); |
handler->onOffer(getSessionHandle(), msg, *sdp); |
849 |
break; |
break; |
850 |
|
|
985 |
break; |
break; |
986 |
|
|
987 |
case On2xxAnswer: |
case On2xxAnswer: |
988 |
case On2xxOffer: |
case On2xxOffer: // !slg! doesn't really make sense |
989 |
{ |
{ |
990 |
transition(Connected); |
transition(Connected); |
991 |
handleSessionTimerResponse(msg); |
handleSessionTimerResponse(msg); |
1074 |
} |
} |
1075 |
|
|
1076 |
void |
void |
1077 |
|
InviteSession::dispatchSentReinviteNoOffer(const SipMessage& msg) |
1078 |
|
{ |
1079 |
|
InviteSessionHandler* handler = mDum.mInviteSessionHandler; |
1080 |
|
std::auto_ptr<SdpContents> sdp = InviteSession::getSdp(msg); |
1081 |
|
|
1082 |
|
switch (toEvent(msg, sdp.get())) |
1083 |
|
{ |
1084 |
|
case OnInvite: |
1085 |
|
case OnInviteReliable: |
1086 |
|
case OnInviteOffer: |
1087 |
|
case OnInviteReliableOffer: |
1088 |
|
case OnUpdate: |
1089 |
|
case OnUpdateOffer: |
1090 |
|
{ |
1091 |
|
SipMessage response; |
1092 |
|
mDialog.makeResponse(response, msg, 491); |
1093 |
|
BaseUsage::send(response); |
1094 |
|
break; |
1095 |
|
} |
1096 |
|
|
1097 |
|
case On1xx: |
1098 |
|
case On1xxEarly: |
1099 |
|
// Some UA's send a 100 response to a ReInvite - just ignore it |
1100 |
|
break; |
1101 |
|
|
1102 |
|
case On2xxAnswer: // !slg! doesn't really make sense |
1103 |
|
case On2xxOffer: |
1104 |
|
{ |
1105 |
|
transition(SentReinviteAnswered); |
1106 |
|
handleSessionTimerResponse(msg); |
1107 |
|
mLastSessionModification = msg; |
1108 |
|
mCurrentEncryptionLevel = getEncryptionLevel(msg); |
1109 |
|
mProposedRemoteSdp = InviteSession::makeSdp(*sdp); |
1110 |
|
handler->onOffer(getSessionHandle(), msg, *sdp); |
1111 |
|
|
1112 |
|
// !jf! do I need to allow a reINVITE overlapping the retransmission of |
1113 |
|
// the ACK when a 200I is received? If yes, then I need to store all |
1114 |
|
// ACK messages for 64*T1 |
1115 |
|
break; |
1116 |
|
} |
1117 |
|
|
1118 |
|
case On2xx: |
1119 |
|
sendAck(); |
1120 |
|
transition(Connected); |
1121 |
|
handleSessionTimerResponse(msg); |
1122 |
|
handler->onIllegalNegotiation(getSessionHandle(), msg); |
1123 |
|
mProposedLocalSdp.release(); |
1124 |
|
mProposedEncryptionLevel = DialogUsageManager::None; |
1125 |
|
break; |
1126 |
|
|
1127 |
|
case On422Invite: |
1128 |
|
if(msg.exists(h_MinSE)) |
1129 |
|
{ |
1130 |
|
// Change interval to min from 422 response |
1131 |
|
mSessionInterval = msg.header(h_MinSE).value(); |
1132 |
|
mMinSE = mSessionInterval; |
1133 |
|
setSessionTimerHeaders(mLastSessionModification); |
1134 |
|
send(mLastSessionModification); |
1135 |
|
} |
1136 |
|
else |
1137 |
|
{ |
1138 |
|
// Response must contact Min_SE - if not - just ignore |
1139 |
|
// ?slg? callback? |
1140 |
|
transition(Connected); |
1141 |
|
mProposedLocalSdp.release(); |
1142 |
|
mProposedEncryptionLevel = DialogUsageManager::None; |
1143 |
|
} |
1144 |
|
break; |
1145 |
|
|
1146 |
|
case On491Invite: |
1147 |
|
transition(SentReinviteNoOfferGlare); |
1148 |
|
start491Timer(); |
1149 |
|
break; |
1150 |
|
|
1151 |
|
case OnGeneralFailure: |
1152 |
|
sendBye(); |
1153 |
|
transition(Terminated); |
1154 |
|
handler->onTerminated(getSessionHandle(), InviteSessionHandler::GeneralFailure, &msg); |
1155 |
|
break; |
1156 |
|
|
1157 |
|
case OnInviteFailure: |
1158 |
|
case On487Invite: |
1159 |
|
case On489Invite: |
1160 |
|
transition(Connected); |
1161 |
|
mProposedLocalSdp.release(); |
1162 |
|
handler->onOfferRejected(getSessionHandle(), &msg); |
1163 |
|
break; |
1164 |
|
|
1165 |
|
default: |
1166 |
|
dispatchOthers(msg); |
1167 |
|
break; |
1168 |
|
} |
1169 |
|
} |
1170 |
|
|
1171 |
|
void |
1172 |
InviteSession::dispatchReceivedReinviteSentOffer(const SipMessage& msg) |
InviteSession::dispatchReceivedReinviteSentOffer(const SipMessage& msg) |
1173 |
{ |
{ |
1174 |
InviteSessionHandler* handler = mDum.mInviteSessionHandler; |
InviteSessionHandler* handler = mDum.mInviteSessionHandler; |
1215 |
{ |
{ |
1216 |
InviteSessionHandler* handler = mDum.mInviteSessionHandler; |
InviteSessionHandler* handler = mDum.mInviteSessionHandler; |
1217 |
MethodTypes method = msg.header(h_CSeq).method(); |
MethodTypes method = msg.header(h_CSeq).method(); |
1218 |
if (method == INVITE && msg.isRequest()) |
if (msg.isRequest() && (method == INVITE || method == UPDATE)) |
1219 |
{ |
{ |
1220 |
// Received inbound reinvite, when waiting to resend outbound reinvite or update |
// Received inbound reinvite or update, when waiting to resend outbound reinvite or update |
|
transition(ReceivedReinvite); |
|
1221 |
handler->onOfferRejected(getSessionHandle(), &msg); |
handler->onOfferRejected(getSessionHandle(), &msg); |
1222 |
|
dispatchConnected(msg); // act as if we received message in Connected state |
1223 |
} |
} |
1224 |
else if (method == UPDATE && msg.isRequest()) |
else |
1225 |
{ |
{ |
1226 |
// Received inbound update, when waiting to resend outbound reinvite or update |
dispatchOthers(msg); |
1227 |
transition(ReceivedUpdate); |
} |
1228 |
handler->onOfferRejected(getSessionHandle(), &msg); |
} |
1229 |
|
|
1230 |
|
void |
1231 |
|
InviteSession::dispatchReinviteNoOfferGlare(const SipMessage& msg) |
1232 |
|
{ |
1233 |
|
InviteSessionHandler* handler = mDum.mInviteSessionHandler; |
1234 |
|
MethodTypes method = msg.header(h_CSeq).method(); |
1235 |
|
if (msg.isRequest() && (method == INVITE || method == UPDATE)) |
1236 |
|
{ |
1237 |
|
// Received inbound reinvite or update, when waiting to resend outbound reinvite or update |
1238 |
|
handler->onOfferRequestRejected(getSessionHandle(), msg); |
1239 |
|
dispatchConnected(msg); // act as if we received message in Connected state |
1240 |
} |
} |
1241 |
else |
else |
1242 |
{ |
{ |
1279 |
} |
} |
1280 |
|
|
1281 |
void |
void |
1282 |
|
InviteSession::dispatchSentReinviteAnswered(const SipMessage& msg) |
1283 |
|
{ |
1284 |
|
dispatchOthers(msg); |
1285 |
|
} |
1286 |
|
|
1287 |
|
void |
1288 |
InviteSession::dispatchWaitingToOffer(const SipMessage& msg) |
InviteSession::dispatchWaitingToOffer(const SipMessage& msg) |
1289 |
{ |
{ |
1290 |
if (msg.isRequest() && msg.header(h_RequestLine).method() == ACK) |
if (msg.isRequest() && msg.header(h_RequestLine).method() == ACK) |
1291 |
{ |
{ |
1292 |
assert(mProposedLocalSdp.get()); |
assert(mProposedLocalSdp.get()); |
1293 |
mCurrentRetransmit200 = 0; // stop the 200 retransmit timer |
mCurrentRetransmit200 = 0; // stop the 200 retransmit timer |
1294 |
if (dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get())) |
provideProposedOffer(); |
|
{ |
|
|
provideOffer( *(dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().back())), |
|
|
mProposedEncryptionLevel, |
|
|
dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().front())); |
|
1295 |
} |
} |
1296 |
else |
else |
1297 |
{ |
{ |
1298 |
provideOffer(*(dynamic_cast<SdpContents*>(mProposedLocalSdp.get())), mProposedEncryptionLevel, 0); |
dispatchOthers(msg); |
1299 |
} |
} |
1300 |
} |
} |
1301 |
|
|
1302 |
|
void |
1303 |
|
InviteSession::dispatchWaitingToRequestOffer(const SipMessage& msg) |
1304 |
|
{ |
1305 |
|
if (msg.isRequest() && msg.header(h_RequestLine).method() == ACK) |
1306 |
|
{ |
1307 |
|
assert(mProposedLocalSdp.get()); |
1308 |
|
mCurrentRetransmit200 = 0; // stop the 200 retransmit timer |
1309 |
|
requestOffer(); |
1310 |
|
} |
1311 |
else |
else |
1312 |
{ |
{ |
1313 |
dispatchOthers(msg); |
dispatchOthers(msg); |
1807 |
return "InviteSession::SentReinvite"; |
return "InviteSession::SentReinvite"; |
1808 |
case SentReinviteGlare: |
case SentReinviteGlare: |
1809 |
return "InviteSession::SentReinviteGlare"; |
return "InviteSession::SentReinviteGlare"; |
1810 |
|
case SentReinviteNoOffer: |
1811 |
|
return "InviteSession::SentReinviteNoOffer"; |
1812 |
|
case SentReinviteAnswered: |
1813 |
|
return "InviteSession::SentReinviteAnswered"; |
1814 |
|
case SentReinviteNoOfferGlare: |
1815 |
|
return "InviteSession::SentReinviteNoOfferGlare"; |
1816 |
case ReceivedUpdate: |
case ReceivedUpdate: |
1817 |
return "InviteSession::ReceivedUpdate"; |
return "InviteSession::ReceivedUpdate"; |
1818 |
case ReceivedReinvite: |
case ReceivedReinvite: |
1825 |
return "InviteSession::Answered"; |
return "InviteSession::Answered"; |
1826 |
case WaitingToOffer: |
case WaitingToOffer: |
1827 |
return "InviteSession::WaitingToOffer"; |
return "InviteSession::WaitingToOffer"; |
1828 |
|
case WaitingToRequestOffer: |
1829 |
|
return "InviteSession::WaitingToRequestOffer"; |
1830 |
case WaitingToTerminate: |
case WaitingToTerminate: |
1831 |
return "InviteSession::WaitingToTerminate"; |
return "InviteSession::WaitingToTerminate"; |
1832 |
case WaitingToHangup: |
case WaitingToHangup: |
1993 |
msg.setContents(sdp); |
msg.setContents(sdp); |
1994 |
} |
} |
1995 |
|
|
1996 |
|
void |
1997 |
|
InviteSession::provideProposedOffer() |
1998 |
|
{ |
1999 |
|
if (dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get())) |
2000 |
|
{ |
2001 |
|
provideOffer( *(dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().back())), |
2002 |
|
mProposedEncryptionLevel, |
2003 |
|
dynamic_cast<SdpContents*>((dynamic_cast<MultipartAlternativeContents*>(mProposedLocalSdp.get()))->parts().front())); |
2004 |
|
} |
2005 |
|
else |
2006 |
|
{ |
2007 |
|
provideOffer(*(dynamic_cast<SdpContents*>(mProposedLocalSdp.get())), mProposedEncryptionLevel, 0); |
2008 |
|
} |
2009 |
|
} |
2010 |
|
|
2011 |
InviteSession::Event |
InviteSession::Event |
2012 |
InviteSession::toEvent(const SipMessage& msg, const SdpContents* sdp) |
InviteSession::toEvent(const SipMessage& msg, const SdpContents* sdp) |
2013 |
{ |
{ |