From: Damien S. <dsa...@us...> - 2005-09-27 16:17:22
|
Update of /cvsroot/openh323/opal/src/sip In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13000/src/sip Modified Files: sipcon.cxx Log Message: - Added SendPDU method and use it everywhere for requests sent in the dialog and to transmit responses to incoming requests. - Fixed again re-INVITE support and 200 OK generation. - Update the route set when receiving responses and requests according to the RFC. - Update the targetAddress to the Contact field when receiving a response. - Transmit the ack for 2xx and non-2xx responses. - Do not update the remote transport address when receiving requests and responses. Do it only in SendPDU as the remote transport address for a response and for a request in a dialog are different. - Populate the route set with an initial route when an outbound proxy should be used as recommended by the RFC. Index: sipcon.cxx =================================================================== RCS file: /cvsroot/openh323/opal/src/sip/sipcon.cxx,v retrieving revision 2.85 retrieving revision 2.86 diff -C2 -d -r2.85 -r2.86 *** sipcon.cxx 21 Sep 2005 21:03:04 -0000 2.85 --- sipcon.cxx 27 Sep 2005 16:17:12 -0000 2.86 *************** *** 25,28 **** --- 25,42 ---- * * $Log$ + * Revision 2.86 2005/09/27 16:17:12 dsandras + * - Added SendPDU method and use it everywhere for requests sent in the dialog + * and to transmit responses to incoming requests. + * - Fixed again re-INVITE support and 200 OK generation. + * - Update the route set when receiving responses and requests according to the + * RFC. + * - Update the targetAddress to the Contact field when receiving a response. + * - Transmit the ack for 2xx and non-2xx responses. + * - Do not update the remote transport address when receiving requests and + * responses. Do it only in SendPDU as the remote transport address for a response + * and for a request in a dialog are different. + * - Populate the route set with an initial route when an outbound proxy should + * be used as recommended by the RFC. + * * Revision 2.85 2005/09/21 21:03:04 dsandras * Fixed reINVITE support. *************** *** 350,357 **** SIPConnection::SIPConnection(OpalCall & call, ! SIPEndPoint & ep, ! const PString & token, ! const SIPURL & destination, ! OpalTransport * inviteTransport) : OpalConnection(call, ep, token), endpoint(ep), --- 364,371 ---- SIPConnection::SIPConnection(OpalCall & call, ! SIPEndPoint & ep, ! const PString & token, ! const SIPURL & destination, ! OpalTransport * inviteTransport) : OpalConnection(call, ep, token), endpoint(ep), *************** *** 375,383 **** proxy = endpoint.GetProxy(); ! // Proxy parameters. if (!proxy.IsEmpty()) { ! targetAddress = proxy.GetScheme() + ':' + proxy.GetHostName() + ':' + PString(proxy.GetPort()); } ! if (inviteTransport == NULL) transport = NULL; --- 389,397 ---- proxy = endpoint.GetProxy(); ! // Default routeSet if (!proxy.IsEmpty()) { ! routeSet += proxy.GetHostName() + ':' + PString(proxy.GetPort()) + ";lr=on"; } ! if (inviteTransport == NULL) transport = NULL; *************** *** 415,462 **** PTRACE(3, "SIP\tOnReleased: " << *this); SIPTransaction * byeTransaction = NULL; switch (releaseMethod) { ! case ReleaseWithNothing : ! break; ! ! case ReleaseWithResponse : ! switch (callEndReason) { ! case EndedByAnswerDenied : ! SendResponseToINVITE(SIP_PDU::GlobalFailure_Decline); ! break; ! ! case EndedByLocalBusy : ! SendResponseToINVITE(SIP_PDU::Failure_BusyHere); ! break; ! case EndedByCallerAbort : ! SendResponseToINVITE(SIP_PDU::Failure_RequestTerminated); ! break; ! // call ended by no codec match or stream open failure ! case EndedByCapabilityExchange : ! SendResponseToINVITE(SIP_PDU::Failure_UnsupportedMediaType); ! break; ! case EndedByCallForwarded : ! SendResponseToINVITE(SIP_PDU::Redirection_MovedTemporarily, forwardParty); ! break; ! default : ! SendResponseToINVITE(SIP_PDU::Failure_BadGateway); ! } break; ! case ReleaseWithBYE : ! // create BYE now & delete it later to prevent memory access errors ! byeTransaction = new SIPTransaction(*this, *transport, SIP_PDU::Method_BYE); break; ! case ReleaseWithCANCEL : ! for (PINDEX i = 0; i < invitations.GetSize(); i++) { ! if (invitations[i].SendCANCEL()) ! invitations[i].Wait(); ! } } --- 429,495 ---- PTRACE(3, "SIP\tOnReleased: " << *this); + SIP_PDU response; SIPTransaction * byeTransaction = NULL; switch (releaseMethod) { ! case ReleaseWithNothing : ! break; ! case ReleaseWithResponse : ! switch (callEndReason) { ! case EndedByAnswerDenied : ! { ! SIP_PDU response(*originalInvite, SIP_PDU::GlobalFailure_Decline); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); ! } ! break; ! case EndedByLocalBusy : ! { ! SIP_PDU response(*originalInvite, SIP_PDU::Failure_BusyHere); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); ! } ! break; ! case EndedByCallerAbort : ! { ! SIP_PDU response(*originalInvite, SIP_PDU::Failure_RequestTerminated); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); ! } ! break; ! // call ended by no codec match or stream open failure ! case EndedByCapabilityExchange : ! { ! SIP_PDU response(*originalInvite, SIP_PDU::Failure_UnsupportedMediaType); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); ! } break; ! case EndedByCallForwarded : ! { ! SIP_PDU response(*originalInvite, SIP_PDU::Redirection_MovedTemporarily, NULL, forwardParty); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); ! } break; ! default : ! { ! SIP_PDU response(*originalInvite, SIP_PDU::Failure_BadGateway); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); ! } ! } ! break; ! ! case ReleaseWithBYE : ! // create BYE now & delete it later to prevent memory access errors ! byeTransaction = new SIPTransaction(*this, *transport, SIP_PDU::Method_BYE); ! break; ! ! case ReleaseWithCANCEL : ! for (PINDEX i = 0; i < invitations.GetSize(); i++) { ! if (invitations[i].SendCANCEL()) ! invitations[i].Wait(); ! } } *************** *** 511,515 **** return FALSE; ! SendResponseToINVITE(SIP_PDU::Information_Ringing); phase = AlertingPhase; --- 544,549 ---- return FALSE; ! SIP_PDU response(*originalInvite, SIP_PDU::Information_Ringing); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); phase = AlertingPhase; *************** *** 557,567 **** } // send the 200 OK response SIPURL contact(endpoint.GetRegisteredPartyName(SIPURL(remotePartyAddress).GetHostName()).GetUserName(), contactAddress, contactPort); SIP_PDU response(*originalInvite, SIP_PDU::Successful_OK, (const char *) contact.AsQuotedString()); response.SetSDP(sdpOut); ! response.Write(*transport); ! phase = ConnectedPhase; connectedTime = PTime (); --- 591,613 ---- } + // update the route set and the target address according to 12.1.1 + // requests in a dialog do not modify the route set according to 12.2 + if (phase < ConnectedPhase) { + routeSet.RemoveAll(); + routeSet = originalInvite->GetMIME().GetRecordRoute(); + PString originalContact = originalInvite->GetMIME().GetContact(); + if (!originalContact.IsEmpty()) { + targetAddress = originalContact; + } + } + // send the 200 OK response SIPURL contact(endpoint.GetRegisteredPartyName(SIPURL(remotePartyAddress).GetHostName()).GetUserName(), contactAddress, contactPort); SIP_PDU response(*originalInvite, SIP_PDU::Successful_OK, (const char *) contact.AsQuotedString()); response.SetSDP(sdpOut); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); + + phase = ConnectedPhase; connectedTime = PTime (); *************** *** 582,594 **** } - // create the list of Opal format names for the remote end remoteFormatList += incomingMedia->GetMediaFormats(rtpSessionId); ! AdjustMediaFormats(remoteFormatList); // find the payload type used for telephone-event, if present const SDPMediaFormatList & sdpMediaList = incomingMedia->GetSDPMediaFormats(); - PINDEX i; BOOL hasTelephoneEvent = FALSE; for (i = 0; !hasTelephoneEvent && (i < sdpMediaList.GetSize()); i++) { --- 628,650 ---- } // create the list of Opal format names for the remote end + // we will answer with the media format that will be opened remoteFormatList += incomingMedia->GetMediaFormats(rtpSessionId); ! remoteFormatList.Remove(endpoint.GetManager().GetMediaFormatMask()); ! if (remoteFormatList.GetSize() == 0) { ! ReleaseSession(rtpSessionId); ! return FALSE; ! } ! PINDEX i; ! for (i = 0; i < remoteFormatList.GetSize(); i++) { ! if (remoteFormatList[i].GetDefaultSessionID() == rtpSessionId) { ! remoteFormatList = remoteFormatList[i]; ! break; ! } ! } // find the payload type used for telephone-event, if present const SDPMediaFormatList & sdpMediaList = incomingMedia->GetSDPMediaFormats(); BOOL hasTelephoneEvent = FALSE; for (i = 0; !hasTelephoneEvent && (i < sdpMediaList.GetSize()); i++) { *************** *** 616,620 **** mediaTransportAddresses.SetAt(rtpSessionId, new OpalTransportAddress(incomingMedia->GetTransportAddress())); } - else { --- 672,675 ---- *************** *** 651,660 **** } // construct a new media session list with the selected format SDPMediaDescription * localMedia = new SDPMediaDescription(localAddress, rtpMediaType); ! SDPSessionDescription *sdp = (SDPSessionDescription *) &sdpOut; ! if ((rtpSessionId == OpalMediaFormat::DefaultVideoSessionID && (endpoint.GetManager().CanAutoStartTransmitVideo() || endpoint.GetManager().CanAutoStartReceiveVideo())) || rtpSessionId == OpalMediaFormat::DefaultAudioSessionID) ! BuildSDP(sdp, rtpSessions, rtpSessionId); // Answer with recvonly if it is a remote hold --- 706,745 ---- } + // find out what media stream was opened + // and get the payload type that was selected + if (mediaStreams.IsEmpty()) { + PTRACE(2, "SIP\tNo media streams opened"); + ReleaseSession(rtpSessionId); + return FALSE; + } + // construct a new media session list with the selected format SDPMediaDescription * localMedia = new SDPMediaDescription(localAddress, rtpMediaType); ! // Locate the opened media stream, add it to the reply and open the reverse direction ! BOOL reverseStreamsFailed = TRUE; ! for (i = 0; i < mediaStreams.GetSize(); i++) { ! OpalMediaStream & mediaStream = mediaStreams[i]; ! if (mediaStream.GetSessionID() == rtpSessionId) { ! OpalMediaFormat mediaFormat = mediaStream.GetMediaFormat(); ! if (OpenSourceMediaStream(mediaFormat, rtpSessionId)) { ! localMedia->AddMediaFormat(mediaFormat); ! reverseStreamsFailed = FALSE; ! } ! } ! } ! ! if (reverseStreamsFailed) { ! PTRACE(2, "SIP\tNo reverse media streams opened"); ! mediaStreams.RemoveAll(); ! delete localMedia; ! ReleaseSession(rtpSessionId); ! return FALSE; ! } ! ! // Add in the RFC2833 handler, if used ! if (hasTelephoneEvent) { ! localMedia->AddSDPMediaFormat(new SDPMediaFormat("0-15", rfc2833Handler->GetPayloadType())); ! } // Answer with recvonly if it is a remote hold *************** *** 669,672 **** --- 754,758 ---- } + sdpOut.AddMediaDescription(localMedia); return TRUE; } *************** *** 1085,1101 **** remoteApplication.Replace ('/', '\t'); ! // Get the route set from the Record-Route response field (in reverse order) ! PStringList recordRoute = response.GetMIME().GetRecordRoute(); ! routeSet.RemoveAll(); ! for (i = recordRoute.GetSize(); i > 0; i--) ! routeSet.AppendString(recordRoute[i-1]); ! } ! // If current SIP dialog does not have a route set (via Record-Route) and ! // this response had a contact field then start using that address for all ! // future communication with remote SIP endpoint ! PString contact = response.GetMIME().GetContact(); ! if (!contact) ! targetAddress = contact; switch (response.GetStatusCode()) { --- 1171,1214 ---- remoteApplication.Replace ('/', '\t'); ! // get the route set from the Record-Route response field (in reverse order) ! // according to 12.1.2 ! // requests in a dialog do not modify the initial route set fo according ! // to 12.2 ! if (phase < ConnectedPhase) { ! PStringList recordRoute = response.GetMIME().GetRecordRoute(); ! routeSet.RemoveAll(); ! for (i = recordRoute.GetSize(); i > 0; i--) ! routeSet.AppendString(recordRoute[i-1]); ! } ! // If we are in a dialog or create one, then targetAddress needs to be set ! // to the contact field in the 2xx/1xx response for a target refresh ! // request ! if (response.GetStatusCode()/100 == 2 ! || response.GetStatusCode()/100 == 1) { ! PString contact = response.GetMIME().GetContact(); ! if (!contact.IsEmpty()) { ! targetAddress = contact; ! PTRACE(4, "SIP\tSet targetAddress to " << targetAddress); ! } ! } ! ! // Send the ack ! if (response.GetStatusCode()/100 != 1) { ! SIP_PDU ack; ! ! // ACK Constructed following 17.1.1.3 ! if (response.GetStatusCode()/100 != 2) ! ack = SIPAck(transaction, response); ! else ! ack = SIPAck(transaction); ! ! // Send the PDU using the connection transport ! if (!SendPDU(ack, ack.GetSendAddress(*this))) { ! Release(EndedByTransportFail); ! return; ! } ! } ! } switch (response.GetStatusCode()) { *************** *** 1200,1214 **** mime.SetTo(localPartyAddress); ! if (!transport->IsReliable()) { ! transport->SetRemoteAddress(request.GetViaAddress(endpoint)); ! PTRACE(4, "SIP\tOnReceivedINVITE Changed remote address of transport " << *transport); ! } ! targetAddress = mime.GetFrom(); targetAddress.AdjustForRequestURI(); // We received a Re-INVITE for a current connection if (isReinvite) { SDPSessionDescription sdpOut(GetLocalAddress()); --- 1313,1328 ---- mime.SetTo(localPartyAddress); ! // update the target address targetAddress = mime.GetFrom(); targetAddress.AdjustForRequestURI(); + + // send trying with To: tag + SIP_PDU response(*originalInvite, SIP_PDU::Information_Trying); + SendPDU(response, originalInvite->GetViaAddress(endpoint)); // We received a Re-INVITE for a current connection if (isReinvite) { + remoteFormatList.RemoveAll(); SDPSessionDescription sdpOut(GetLocalAddress()); *************** *** 1270,1282 **** SIP_PDU response(*originalInvite, SIP_PDU::Successful_OK, (const char *) contact.AsQuotedString ()); response.SetSDP(sdpOut); ! ! response.Write(*transport); return; } - // send trying with To: tag - SendResponseToINVITE(SIP_PDU::Information_Trying); - // indicate the other is to start ringing --- 1384,1392 ---- SIP_PDU response(*originalInvite, SIP_PDU::Successful_OK, (const char *) contact.AsQuotedString ()); response.SetSDP(sdpOut); ! SendPDU(response, originalInvite->GetViaAddress(endpoint)); return; } // indicate the other is to start ringing *************** *** 1396,1400 **** SIP_PDU response(pdu, SIP_PDU::Failure_BadEvent); ! response.Write(*transport); return; } --- 1506,1510 ---- SIP_PDU response(pdu, SIP_PDU::Failure_BadEvent); ! SendPDU(response, pdu.GetViaAddress(endpoint)); return; } *************** *** 1410,1414 **** // The REFER is not over yet, ignore the state of the REFER for now SIP_PDU response(pdu, SIP_PDU::Successful_OK); ! response.Write(*transport); } --- 1520,1524 ---- // The REFER is not over yet, ignore the state of the REFER for now SIP_PDU response(pdu, SIP_PDU::Successful_OK); ! SendPDU(response, pdu.GetViaAddress(endpoint)); } *************** *** 1421,1432 **** if (referto.IsEmpty()) { SIP_PDU response(pdu, SIP_PDU::Failure_BadEvent); ! response.Write(*transport); return; } - // Reject the Refer - //SIP_PDU response(pdu, SIP_PDU::GlobalFailure_Decline); - //response.Write(*transport); - endpoint.SetupTransfer(GetToken(), PString (), --- 1531,1538 ---- if (referto.IsEmpty()) { SIP_PDU response(pdu, SIP_PDU::Failure_BadEvent); ! SendPDU(response, pdu.GetViaAddress(endpoint)); return; } endpoint.SetupTransfer(GetToken(), PString (), *************** *** 1444,1448 **** PTRACE(2, "SIP\tBYE received for call " << request.GetMIME().GetCallID()); SIP_PDU response(request, SIP_PDU::Successful_OK); ! response.Write(*transport); releaseMethod = ReleaseWithNothing; --- 1550,1554 ---- PTRACE(2, "SIP\tBYE received for call " << request.GetMIME().GetCallID()); SIP_PDU response(request, SIP_PDU::Successful_OK); ! SendPDU(response, request.GetViaAddress(endpoint)); releaseMethod = ReleaseWithNothing; *************** *** 1478,1482 **** PTRACE(1, "SIP\tUnattached " << request << " received for " << *this); SIP_PDU response(request, SIP_PDU::Failure_TransactionDoesNotExist); ! response.Write(*transport); return; } --- 1584,1588 ---- PTRACE(1, "SIP\tUnattached " << request << " received for " << *this); SIP_PDU response(request, SIP_PDU::Failure_TransactionDoesNotExist); ! SendPDU(response, request.GetViaAddress(endpoint)); return; } *************** *** 1485,1489 **** SIP_PDU response(request, SIP_PDU::Successful_OK); ! response.Write(*transport); Release(EndedByCallerAbort); } --- 1591,1595 ---- SIP_PDU response(request, SIP_PDU::Successful_OK); ! SendPDU(response, request.GetViaAddress(endpoint)); Release(EndedByCallerAbort); } *************** *** 1786,1797 **** ! void SIPConnection::SendResponseToINVITE(SIP_PDU::StatusCodes code, const char * extra) { ! if (originalInvite != NULL) { ! ! SIP_PDU response(*originalInvite, code, NULL, extra); ! if (transport) ! response.Write(*transport); } } --- 1892,1906 ---- ! BOOL SIPConnection::SendPDU(SIP_PDU & pdu, const OpalTransportAddress & address) { ! if (transport) { ! ! PWaitAndSignal m(transportMutex); ! PTRACE(3, "SIP\tAdjusting transport to address " << address); ! transport->SetRemoteAddress(address); ! return (pdu.Write(*transport)); } + + return FALSE; } |