internal TSIP_Transac CreateTransac(Boolean isClient, TSIP_Message message, TSIP_Dialog dialog) { TSIP_Transac transac = null; if (message != null && message.IsRequest) { if (isClient)/* Client transaction */ { if (message.IsINVITE) { // INVITE Client transaction (ICT) TSK_Debug.Error("CreateTransac - not implemented"); } else { // NON-INVITE Client transaction (NICT) transac = new TSIP_TransacNICT(mReliable, (Int32)message.CSeq.CSeq, message.CSeq.Method, message.CallId.Value, dialog); } } else/* Server transaction */ { if (message.IsINVITE) { // INVITE Server transaction (IST) TSK_Debug.Error("CreateTransac - not implemented"); } else { // NON-INVITE Server transaction (NIST) TSK_Debug.Error("CreateTransac - not implemented"); } if (transac != null) { /* Copy branch from the message */ transac.Branch = message.FirstVia.Branch; } } } mMutex.WaitOne(); if (transac != null) { /* Add new transaction */ mTransactions.Add(transac.Id, transac); } mMutex.ReleaseMutex(); return(transac); }
internal TSIP_Transac FindClientTransacByMsg(TSIP_Response response) { /* RFC 3261 - 17.1.3 Matching Responses to Client Transactions * * When the transport layer in the client receives a response, it has to * determine which client transaction will handle the response, so that * the processing of Sections 17.1.1 and 17.1.2 can take place. The * branch parameter in the top Via header field is used for this * purpose. A response matches a client transaction under two * conditions: * * 1. If the response has the same value of the branch parameter in * the top Via header field as the branch parameter in the top * Via header field of the request that created the transaction. * * 2. If the method parameter in the CSeq header field matches the * method of the request that created the transaction. The * method is needed since a CANCEL request constitutes a * different transaction, but shares the same value of the branch * parameter. */ if (response == null || response.FirstVia == null || response.CSeq == null) { return(null); } TSIP_Transac transac = null; mMutex.WaitOne(); foreach (TSIP_Transac t in mTransactions.Values) { if (String.Equals(t.Branch, response.FirstVia.Branch) && String.Equals(t.CSeqMethod, response.CSeq.Method)) { transac = t; break; } } mMutex.ReleaseMutex(); return(transac); }
internal Boolean HandleIncomingMsg(TSIP_Message message) { TSIP_Transac transac = null; if (message.IsRequest) { transac = this.FindServerTransacByMsg(message); } else { transac = this.FindClientTransacByMsg((message as TSIP_Response)); } if (transac != null) { return(transac.RaiseCallback(TSIP_Transac.tsip_transac_event_type_t.IncomingMessage, message)); } return(false); }
internal TSIP_Transac FindServerTransacByMsg(TSIP_Message message) { /* * RFC 3261 - 17.2.3 Matching Requests to Server Transactions * * When a request is received from the network by the server, it has to * be matched to an existing transaction. This is accomplished in the * following manner. * * The branch parameter in the topmost Via header field of the request * is examined. If it is present and begins with the magic cookie * "z9hG4bK", the request was generated by a client transaction * compliant to this specification. Therefore, the branch parameter * will be unique across all transactions sent by that client. The * request matches a transaction if: * * 1. the branch parameter in the request is equal to the one in the * top Via header field of the request that created the * transaction, and * * 2. the sent-by value in the top Via of the request is equal to the * one in the request that created the transaction, and * * 3. the method of the request matches the one that created the * transaction, except for ACK, where the method of the request * that created the transaction is INVITE. */ if (message == null || message.FirstVia == null || message.CSeq == null) { return(null); } TSIP_Transac transac = null; mMutex.WaitOne(); foreach (TSIP_Transac t in mTransactions.Values) { /* 1. ACK branch won't match INVITE's but they MUST have the same CSeq/CallId values */ if (message.IsACK && String.Equals(t.CallId, message.CallId.Value)) { if (String.Equals(t.CSeqMethod, TSIP_Request.METHOD_INVITE) && message.CSeq.CSeq == t.CSeqValue) { transac = t; break; } } else if (String.Equals(t.Branch, message.FirstVia.Branch) && (1 == 1))/* FIXME: compare host:ip */ { if (String.Equals(t.CSeqMethod, message.CSeq.Method)) { transac = t; break; } else if (message.IsCANCEL || (message.IsResponse && message.CSeq.RequestType == TSIP_Message.tsip_request_type_t.CANCEL)) { transac = t; break; } } } mMutex.ReleaseMutex(); return(transac); }