protected Boolean SenRequest(TSIP_Request request) { TSIP_Transac transact = this.Stack.LayerTransac.CreateTransac(true, request, this); switch (transact.Type) { case TSIP_Transac.tsip_transac_type_t.ICT: case TSIP_Transac.tsip_transac_type_t.NICT: { /* Start the newly create IC/NIC transaction */ return(transact.Start(request)); } } return(false); }
internal TSIP_Header CreateHeaderAuthorization(TSIP_Request request) { if (request == null) { TSK_Debug.Error("Invalid parameter"); return(null); } String response, nc = null, uristring; if (String.IsNullOrEmpty(uristring = TSIP_Uri.ToString(request.Uri, true, false))) { TSK_Debug.Error("Failed to parse URI: {0}", request.Uri); return(null); } /* We compute the nc here because @ref tsip_challenge_get_response function will increment it's value. */ if (mNc > 0) { nc = THTTP_Auth.GetNonceString(mNc).ToString(); } /* entity_body ==> request-content */ response = GetResponse(request.Method, uristring, request.Content); if (mProxy) { // FIXME TSK_Debug.Error("Proxy-Authorization header not supported yet"); } else { TSIP_HeaderAuthorization header = new TSIP_HeaderAuthorization(); header.UserName = ChallengeUserName; header.Scheme = mScheme; header.Realm = mRealm; header.Nonce = mNonce; header.Qop = mQop; header.Algorithm = String.IsNullOrEmpty(mAlgorithm) ? "MD5" : mAlgorithm; header.Cnonce = mNc > 0 ? mCnonce : null; header.Uri = uristring; header.Nc = mNc > 0 ? nc : null; header.Response = response; return(header); } return(null); }
private Boolean SendRegister(Boolean initial) { TSIP_Request request = base.CreateRequest(TSIP_Request.METHOD_REGISTER); Boolean ret = false; /* 3GPP TS 24.229 - 5.1.1.2 Initial registration */ if (base.State == tsip_dialog_state_t.Initial) { /* * g) the Supported header field containing the option-tag "path", and * 1) if GRUU is supported, the option-tag "gruu"; and * 2) if multiple registrations is supported, the option-tag "outbound". */ request.AddHeader(new TSIP_HeaderSupported("path")); } /* action parameters and payload */ if (base.CurrentAction != null) { foreach (TSK_Param param in base.CurrentAction.Headers) { request.AddHeader(new TSIP_HeaderDummy(param.Name, param.Value)); } if (base.CurrentAction.Payload != null) { request.AddContent(null, base.CurrentAction.Payload); } } /* create temorary IPSec SAs if initial register. */ // send the request ret = base.SenRequest(request); if (ret) { base.Signal(TSIP_EventDialog.tsip_dialog_event_type_t.RequestSent, "(un)REGISTER request successfully sent"); } else { base.Signal(TSIP_EventDialog.tsip_dialog_event_type_t.TransportError, "Transport error"); } return(ret); }
protected Boolean UpdateWithINVITE(TSIP_Request invite) { if (invite == null) { return(false); } /* Remote target */ if (invite.Contact != null && invite.Contact.Uri != null) { mUriRemoteTarget = invite.Contact.Uri.Clone(true, false); } /* cseq + tags + remote-uri */ mTagRemote = invite.From != null ? invite.From.Tag : "doubango"; /* self->cseq_value = invite->CSeq ? invite->CSeq->seq : self->cseq_value; */ if (invite.From != null && invite.From.Uri != null) { mUriRemote = invite.From.Uri; } /* Route sets */ { int index; TSIP_HeaderRecordRoute recordRoute; mRecordRoutes.Clear(); for (index = 0; (recordRoute = (invite.GetHeaderAtIndex(TSIP_Header.tsip_header_type_t.Record_Route, index)) as TSIP_HeaderRecordRoute) != null; index++) { mRecordRoutes.Insert(0, recordRoute); /* Copy non-reversed. */ } } this.State = tsip_dialog_state_t.Established; return(true); }
internal override Boolean Start(TSIP_Request request) { if (request != null && !base.Running) { /* Add branch to the new client transaction * IMPORTANT: CANCEL will have the same Via and Contact headers as the request it cancel */ if (request.IsCANCEL) { base.Branch = request.FirstVia != null ? request.FirstVia.Branch : "doubango"; } else { base.Branch = String.Format("{0}_{1}", TSIP_Transac.MAGIC_COOKIE, TSK_String.Random()); } base.Running = true; mRequest = request; return(base.ExecuteAction((Int32)FSMAction.Send, request)); } return(false); }
private void AddCommonHeaders(TSIP_Request request) { // // P-Preferred-Identity // if (this.Stack.PreferredIdentity != null) { /* 3GPP TS 33.978 6.2.3.1 Procedures at the UE * The UE shall use the temporary public user identity (IMSI-derived IMPU, cf. section 6.1.2) only in registration * messages (i.e. initial registration, re-registration or de-registration), but not in any other type of SIP requests. */ switch (request.RequestType) { case TSIP_Message.tsip_request_type_t.BYE: case TSIP_Message.tsip_request_type_t.INVITE: case TSIP_Message.tsip_request_type_t.OPTIONS: case TSIP_Message.tsip_request_type_t.SUBSCRIBE: case TSIP_Message.tsip_request_type_t.NOTIFY: case TSIP_Message.tsip_request_type_t.REFER: case TSIP_Message.tsip_request_type_t.MESSAGE: case TSIP_Message.tsip_request_type_t.PUBLISH: case TSIP_Message.tsip_request_type_t.REGISTER: { if (!this.Stack.EarlyIMS || (this.Stack.EarlyIMS && request.IsREGISTER)) { // FIXME // TSIP_MESSAGE_ADD_HEADER(request, TSIP_HEADER_P_PREFERRED_IDENTITY_VA_ARGS(preferred_identity)); } break; } } // // P-Access-Network-Info // } }
internal abstract Boolean Start(TSIP_Request request);
internal override Boolean Start(TSIP_Request request) { return false; }
internal override Boolean Start(TSIP_Request request) { return(false); }
protected TSIP_Request CreateRequest(String method) { TSIP_Request request = null; TSIP_Uri to_uri, from_uri, request_uri; String call_id; int copy_routes_start = -1; /* NONE */ /* * RFC 3261 - 12.2.1.1 Generating the Request * * The Call-ID of the request MUST be set to the Call-ID of the dialog. */ call_id = mCallId; /* * RFC 3261 - 12.2.1.1 Generating the Request * * Requests within a dialog MUST contain strictly monotonically * increasing and contiguous CSeq sequence numbers (increasing-by-one) * in each direction (excepting ACK and CANCEL of course, whose numbers * equal the requests being acknowledged or cancelled). Therefore, if * the local sequence number is not empty, the value of the local * sequence number MUST be incremented by one, and this value MUST be * placed into the CSeq header field. */ /*if(!tsk_striequals(method, "ACK") && !tsk_striequals(method, "CANCEL")) * { * TSIP_DIALOG(self)->cseq_value +=1; * } * ===> See send method (cseq will be incremented before sending the request) */ /* * RFC 3261 - 12.2.1.1 Generating the Request * * The URI in the To field of the request MUST be set to the remote URI * from the dialog state. The tag in the To header field of the request * MUST be set to the remote tag of the dialog ID. The From URI of the * request MUST be set to the local URI from the dialog state. The tag * in the From header field of the request MUST be set to the local tag * of the dialog ID. If the value of the remote or local tags is null, * the tag parameter MUST be omitted from the To or From header fields, * respectively. */ to_uri = mUriRemote; from_uri = mUriLocal; /* * RFC 3261 - 12.2.1.1 Generating the Request * * If the route set is empty, the UAC MUST place the remote target URI * into the Request-URI. The UAC MUST NOT add a Route header field to * the request. */ if (mRecordRoutes == null || mRecordRoutes.Count == 0) { request_uri = mUriRemoteTarget; } /* * RFC 3261 - 12.2.1.1 Generating the Request * * If the route set is not empty, and the first URI in the route set * contains the lr parameter (see Section 19.1.1), the UAC MUST place * the remote target URI into the Request-URI and MUST include a Route * header field containing the route set values in order, including all * parameters. * * If the route set is not empty, and its first URI does not contain the * lr parameter, the UAC MUST place the first URI from the route set * into the Request-URI, stripping any parameters that are not allowed * in a Request-URI. The UAC MUST add a Route header field containing * the remainder of the route set values in order, including all * parameters. The UAC MUST then place the remote target URI into the * Route header field as the last value. * * For example, if the remote target is sip:user@remoteua and the route * set contains: * * <sip:proxy1>,<sip:proxy2>,<sip:proxy3;lr>,<sip:proxy4> */ else { TSIP_Uri first_route = mRecordRoutes[0].Uri; if (TSK_Param.HasParam(first_route.Params, "lr")) { request_uri = mUriRemoteTarget; copy_routes_start = 0; /* Copy all */ } else { request_uri = first_route; copy_routes_start = 1; /* Copy starting at index 1. */ } } /*===================================================================== */ request = new TSIP_Request(method, request_uri, from_uri, to_uri, call_id, (Int32)mCSeqValue); request.To.Tag = mTagRemote; request.From.Tag = mTagLocal; request.ShouldUpdate = true; /* Now signal that the message should be updated by the transport layer (Contact, SigComp, IPSec, ...) */ /* * RFC 3261 - 12.2.1.1 Generating the Request * * A UAC SHOULD include a Contact header field in any target refresh * requests within a dialog, and unless there is a need to change it, * the URI SHOULD be the same as used in previous requests within the * dialog. If the "secure" flag is true, that URI MUST be a SIPS URI. * As discussed in Section 12.2.2, a Contact header field in a target * refresh request updates the remote target URI. This allows a UA to * provide a new contact address, should its address change during the * duration of the dialog. */ switch (request.RequestType) { case TSIP_Message.tsip_request_type_t.MESSAGE: case TSIP_Message.tsip_request_type_t.PUBLISH: case TSIP_Message.tsip_request_type_t.BYE: { if (request.RequestType == TSIP_Message.tsip_request_type_t.PUBLISH) { request.AddHeader(new TSIP_HeaderExpires(mExpires)); } /* add caps in Accept-Contact headers */ foreach (TSK_Param param in mSipSession.Caps) { request.AddHeader(new TSIP_HeaderDummy("Accept-Contact", String.Format("*;{0}{1}{2}", param.Name, !String.IsNullOrEmpty(param.Value) ? "=" : String.Empty, !String.IsNullOrEmpty(param.Value) ? param.Value : String.Empty) )); } break; } default: { String contact = null; List <TSIP_HeaderContact> hdr_contacts = null; if (request.RequestType == TSIP_Message.tsip_request_type_t.OPTIONS || request.RequestType == TSIP_Message.tsip_request_type_t.PUBLISH || request.RequestType == TSIP_Message.tsip_request_type_t.REGISTER) { /**** with expires */ contact = String.Format("m: <{0}:{1}@{2}:{3}>;expires={4}\r\n", "sip", from_uri.UserName, "127.0.0.1", 5060, TSK_Time.Milliseconds2Seconds(mExpires)); } else { /**** without expires */ if (request.RequestType == TSIP_Message.tsip_request_type_t.SUBSCRIBE) { /* RFC 3265 - 3.1.1. Subscription Duration * An "expires" parameter on the "Contact" header has no semantics for SUBSCRIBE and is explicitly * not equivalent to an "Expires" header in a SUBSCRIBE request or response. */ request.AddHeader(new TSIP_HeaderExpires(TSK_Time.Milliseconds2Seconds(mExpires))); } contact = String.Format("m: <{0}:{1}@{2}:{3}>\r\n", "sip", from_uri.UserName, "127.0.0.1", 5060); } hdr_contacts = TSIP_HeaderContact.Parse(contact); if (hdr_contacts != null && hdr_contacts.Count > 0) { request.Contact = hdr_contacts[0]; } /* Add capabilities as per RFC 3840 */ if (request.Contact != null) { foreach (TSK_Param param in mSipSession.Caps) { request.Contact.Params = TSK_Param.AddParam(request.Contact.Params, param.Name, param.Value); } } break; } } /* Update authorizations */ if (mState == tsip_dialog_state_t.Initial && mChallenges == null || mChallenges.Count == 0) { /* 3GPP TS 33.978 6.2.3.1 Procedures at the UE * On sending a REGISTER request in order to indicate support for early IMS security procedures, the UE shall not * include an Authorization header field and not include header fields or header field values as required by RFC3329. */ if (request.IsREGISTER && !this.Stack.EarlyIMS) { /* 3GPP TS 24.229 - 5.1.1.2.2 Initial registration using IMS AKA * On sending a REGISTER request, the UE shall populate the header fields as follows: * a) an Authorization header field, with: * - the "username" header field parameter, set to the value of the private user identity; * - the "realm" header field parameter, set to the domain name of the home network; * - the "uri" header field parameter, set to the SIP URI of the domain name of the home network; * - the "nonce" header field parameter, set to an empty value; and * - the "response" header field parameter, set to an empty value; */ String realm = this.Stack.Realm != null ? this.Stack.Realm.Host : "(null)"; String request_uri_ = TSIP_Uri.ToString(request.Uri, false, false); TSIP_Header auth_hdr = TSIP_Challenge.CreateEmptyAuthorization(this.Stack.PrivateIdentity, realm, request_uri_); if (auth_hdr != null) { request.AddHeader(auth_hdr); } } } else if (mChallenges != null && mChallenges.Count > 0) { TSIP_Header auth_hdr; foreach (TSIP_Challenge challenge in mChallenges) { auth_hdr = challenge.CreateHeaderAuthorization(request); if (auth_hdr != null) { request.AddHeader(auth_hdr); } } } /* Update CSeq */ /* RFC 3261 - 13.2.2.4 2xx Responses * Generating ACK: The sequence number of the CSeq header field MUST be * the same as the INVITE being acknowledged, but the CSeq method MUST * be ACK. The ACK MUST contain the same credentials as the INVITE. If * the 2xx contains an offer (based on the rules above), the ACK MUST * carry an answer in its body. * ==> CSeq number will be added/updated by the caller of this function, * credentials were added above. */ if (!request.IsACK && !request.IsCANCEL) { request.CSeq.CSeq = ++mCSeqValue; } /* Route generation * ==> http://betelco.blogspot.com/2008/11/proxy-and-service-route-discovery-in.html * The dialog Routes have been copied above. * * 3GPP TS 24.229 - 5.1.2A.1 UE-originating case * * The UE shall build a proper preloaded Route header field value for all new dialogs and standalone transactions. The UE * shall build a list of Route header field values made out of the following, in this order: * a) the P-CSCF URI containing the IP address or the FQDN learnt through the P-CSCF discovery procedures; and * b) the P-CSCF port based on the security mechanism in use: * * - if IMS AKA or SIP digest with TLS is in use as a security mechanism, the protected server port learnt during * the registration procedure; * - if SIP digest without TLS, NASS-IMS bundled authentciation or GPRS-IMS-Bundled authentication is in * use as a security mechanism, the unprotected server port used during the registration procedure; * c) and the values received in the Service-Route header field saved from the 200 (OK) response to the last * registration or re-registration of the public user identity with associated contact address. */ if (!request.IsREGISTER) { // According to the above link ==> Initial/Re/De registration do not have routes. if (copy_routes_start != -1) { /* The dialog already have routes ==> copy them. */ if (mState == tsip_dialog_state_t.Early || mState == tsip_dialog_state_t.Established) { Int32 index = -1; foreach (TSIP_HeaderRecordRoute record_route in mRecordRoutes) { TSIP_Uri uri = record_route.Uri; if (++index < copy_routes_start || uri == null) { continue; } TSIP_HeaderRoute route = new TSIP_HeaderRoute(uri); // copy parameters: see http://code.google.com/p/imsdroid/issues/detail?id=52 route.Params.AddRange(record_route.Params); request.AddHeader(route); } } } } else {/* No routes associated to this dialog. */ if (mState == tsip_dialog_state_t.Initial || mState == tsip_dialog_state_t.Early) { /* GPP TS 24.229 section 5.1.2A [Generic procedures applicable to all methods excluding the REGISTER method]: * The UE shall build a proper preloaded Route header field value for all new dialogs and standalone transactions. The UE * shall build a list of Route header field values made out of the following, in this order: * a) the P-CSCF URI containing the IP address or the FQDN learnt through the P-CSCF discovery procedures; and * b) the P-CSCF port based on the security mechanism in use: * - if IMS AKA or SIP digest with TLS is in use as a security mechanism, the protected server port learnt during * the registration procedure; * - if SIP digest without TLS, NASS-IMS bundled authentciation or GPRS-IMS-Bundled authentication is in * use as a security mechanism, the unprotected server port used during the registration procedure; * c) and the values received in the Service-Route header field saved from the 200 (OK) response to the last * registration or re-registration of the public user identity with associated contact address. */ #if _DEBUG && SDS_HACK /* Ericsson SDS hack (INVITE with Proxy-CSCF as First route fail) */ #else TSIP_Uri uri = this.Stack.GetProxyCSCFUri(true); // Proxy-CSCF as first route if (uri != null) { request.AddHeader(new TSIP_HeaderRoute(uri)); } #endif // Service routes foreach (TSIP_Uri uriServiceRoute in mServiceRoutes) { request.AddHeader(new TSIP_HeaderRoute(uriServiceRoute)); } } } /* Add headers associated to the dialog's session */ foreach (TSK_Param param in mSipSession.Headers) { request.AddHeader(new TSIP_HeaderDummy(param.Name, param.Value)); } /* Add headers associated to the dialog's stack */ foreach (TSK_Param param in this.Stack.Headers) { request.AddHeader(new TSIP_HeaderDummy(param.Name, param.Value)); } /* Add common headers */ this.AddCommonHeaders(request); /* SigComp */ return(request); }
internal override Boolean Start(TSIP_Request request) { if (request != null && !base.Running) { /* Add branch to the new client transaction * IMPORTANT: CANCEL will have the same Via and Contact headers as the request it cancel */ if (request.IsCANCEL) { base.Branch = request.FirstVia != null ? request.FirstVia.Branch : "doubango"; } else { base.Branch = String.Format("{0}_{1}", TSIP_Transac.MAGIC_COOKIE, TSK_String.Random()); } base.Running = true; mRequest = request; return base.ExecuteAction((Int32)FSMAction.Send, request); } return false; }
private static TSIP_Message Execute(ref TSK_RagelState state, Boolean extractContent) { int cs = state.CS; int p = state.P; int pe = state.PE; int eof = state.EOF; byte[] data = state.Data; TSIP_Message message = null; /* #line 233 "../Parsers/TSIP_ParserMessage.cs" */ { sbyte _klen; byte _trans; int _widec; sbyte _acts; sbyte _nacts; byte _keys; if (p == pe) { goto _test_eof; } if (cs == 0) { goto _out; } _resume: _widec = data[p]; _klen = _tsip_machine_parser_message_cond_lengths[cs]; _keys = (byte)(_tsip_machine_parser_message_cond_offsets[cs] * 2); if (_klen > 0) { short _lower = _keys; short _mid; short _upper = (short)(_keys + (_klen << 1) - 2); while (true) { if (_upper < _lower) { break; } _mid = (short)(_lower + (((_upper - _lower) >> 1) & ~1)); if (_widec < _tsip_machine_parser_message_cond_keys[_mid]) { _upper = (short)(_mid - 2); } else if (_widec > _tsip_machine_parser_message_cond_keys[_mid + 1]) { _lower = (short)(_mid + 2); } else { switch (_tsip_machine_parser_message_cond_spaces[_tsip_machine_parser_message_cond_offsets[cs] + ((_mid - _keys) >> 1)]) { case 0: { _widec = (int)(65536u + (data[p] - 0u)); if ( /* #line 29 "./ragel/tsip_parser_message.rl" */ PrevNotComma(state, p) ) { _widec += 65536; } break; } default: break; } break; } } } _keys = _tsip_machine_parser_message_key_offsets[cs]; _trans = (byte)_tsip_machine_parser_message_index_offsets[cs]; _klen = _tsip_machine_parser_message_single_lengths[cs]; if (_klen > 0) { short _lower = _keys; short _mid; short _upper = (short)(_keys + _klen - 1); while (true) { if (_upper < _lower) { break; } _mid = (short)(_lower + ((_upper - _lower) >> 1)); if (_widec < _tsip_machine_parser_message_trans_keys[_mid]) { _upper = (short)(_mid - 1); } else if (_widec > _tsip_machine_parser_message_trans_keys[_mid]) { _lower = (short)(_mid + 1); } else { _trans += (byte)(_mid - _keys); goto _match; } } _keys += (byte)_klen; _trans += (byte)_klen; } _klen = _tsip_machine_parser_message_range_lengths[cs]; if (_klen > 0) { short _lower = _keys; short _mid; short _upper = (short)(_keys + (_klen << 1) - 2); while (true) { if (_upper < _lower) { break; } _mid = (short)(_lower + (((_upper - _lower) >> 1) & ~1)); if (_widec < _tsip_machine_parser_message_trans_keys[_mid]) { _upper = (short)(_mid - 2); } else if (_widec > _tsip_machine_parser_message_trans_keys[_mid + 1]) { _lower = (short)(_mid + 2); } else { _trans += (byte)((_mid - _keys) >> 1); goto _match; } } _trans += (byte)_klen; } _match: _trans = (byte)_tsip_machine_parser_message_indicies[_trans]; cs = _tsip_machine_parser_message_trans_targs[_trans]; if (_tsip_machine_parser_message_trans_actions[_trans] == 0) { goto _again; } _acts = _tsip_machine_parser_message_trans_actions[_trans]; _nacts = _tsip_machine_parser_message_actions[_acts++]; while (_nacts-- > 0) { switch (_tsip_machine_parser_message_actions[_acts++]) { case 0: /* #line 30 "./ragel/tsip_parser_message.rl" */ { state.TagStart = p; } break; case 1: /* #line 36 "./ragel/tsip_parser_message.rl" */ { int len; state.TagEnd = p; len = (int)(state.TagEnd - state.TagStart); String method = Encoding.UTF8.GetString(data, state.TagStart, len); if (message == null) { message = new TSIP_Request(method, null, null, null, null, 0); } else { state.CS = tsip_machine_parser_message_error; } } break; case 2: /* #line 53 "./ragel/tsip_parser_message.rl" */ { int len; state.TagEnd = p; len = (int)(state.TagEnd - state.TagStart); if ((message as TSIP_Request).Uri == null) { (message as TSIP_Request).Uri = TSIP_ParserUri.Parse(Encoding.UTF8.GetString(state.Data, state.TagStart, len)); } } break; case 3: /* #line 65 "./ragel/tsip_parser_message.rl" */ { int len; state.TagEnd = p; len = (int)(state.TagEnd - state.TagStart); if (message == null) { message = new TSIP_Response(0, null, null); } message.Version = Encoding.UTF8.GetString(state.Data, state.TagStart, len); } break; case 4: /* #line 79 "./ragel/tsip_parser_message.rl" */ { int len; state.TagEnd = p; len = (int)(state.TagEnd - state.TagStart); if (message == null) { message = new TSIP_Response(0, null, null); } UInt16 statusCode = 0; if (UInt16.TryParse(Encoding.UTF8.GetString(state.Data, state.TagStart, len), out statusCode)) { (message as TSIP_Response).StatusCode = statusCode; } } break; case 5: /* #line 98 "./ragel/tsip_parser_message.rl" */ { int len; state.TagEnd = p; len = (int)(state.TagEnd - state.TagStart); (message as TSIP_Response).ReasonPhrase = Encoding.UTF8.GetString(state.Data, state.TagStart, len); } break; case 6: /* #line 107 "./ragel/tsip_parser_message.rl" */ { int len; state.TagEnd = p; len = (int)(state.TagEnd - state.TagStart); if (!TSIP_ParserHeader.Parse(state, ref message)) { TSK_Debug.Error("Failed to parse header at {0}", state.TagStart); } } break; case 7: /* #line 119 "./ragel/tsip_parser_message.rl" */ { state.CS = cs; state.P = p; state.PE = pe; state.EOF = eof; TSIP_ParserMessage.EoH(ref state, ref message, extractContent); cs = state.CS; p = state.P; pe = state.PE; eof = state.EOF; } break; /* #line 447 "../Parsers/TSIP_ParserMessage.cs" */ default: break; } } _again: if (cs == 0) { goto _out; } if (++p != pe) { goto _resume; } _test_eof : {} _out : {} } /* #line 192 "./ragel/tsip_parser_message.rl" */ state.CS = cs; state.P = p; state.PE = pe; state.EOF = eof; return(message); }
internal TSIP_Header CreateHeaderAuthorization(TSIP_Request request) { if (request == null) { TSK_Debug.Error("Invalid parameter"); return null; } String response, nc = null, uristring; if (String.IsNullOrEmpty(uristring = TSIP_Uri.ToString(request.Uri, true, false))) { TSK_Debug.Error("Failed to parse URI: {0}", request.Uri); return null; } /* We compute the nc here because @ref tsip_challenge_get_response function will increment it's value. */ if (mNc > 0) { nc = THTTP_Auth.GetNonceString(mNc).ToString(); } /* entity_body ==> request-content */ response = GetResponse(request.Method, uristring, request.Content); if (mProxy) { // FIXME TSK_Debug.Error("Proxy-Authorization header not supported yet"); } else { TSIP_HeaderAuthorization header = new TSIP_HeaderAuthorization(); header.UserName = ChallengeUserName; header.Scheme = mScheme; header.Realm = mRealm; header.Nonce = mNonce; header.Qop = mQop; header.Algorithm = String.IsNullOrEmpty(mAlgorithm) ? "MD5" : mAlgorithm; header.Cnonce = mNc > 0 ? mCnonce : null; header.Uri = uristring; header.Nc = mNc > 0 ? nc : null; header.Response = response; return header; } return null; }