public TSIP_HeaderContact(String displayName, TSIP_Uri uri, Int64 expires) : base(tsip_header_type_t.Contact) { mDisplayName = displayName; mUri = uri; mExpires = expires; }
public TSIP_HeaderFrom(String displayName, TSIP_Uri uri, String tag) : base(tsip_header_type_t.From) { this.DisplayName = displayName; this.Uri = uri; this.Tag = tag; }
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); }
internal TSIP_Uri GetUri(Boolean lr) { Boolean ipv6 = TNET_Socket.IsIPv6Type(this.Type); String uristring = String.Format("{0}:{1}{2}{3}:{4};{5};transport={6}", this.Scheme, ipv6 ? "[" : String.Empty, mStack.AoRIP, ipv6 ? "]" : String.Empty, mStack.AoRPort, lr ? "lr" : String.Empty, this.Protocol); TSIP_Uri uri = TSIP_ParserUri.Parse(uristring); uri.HostType = ipv6 ? tsip_host_type_t.IPv6 : tsip_host_type_t.IPv4; return(uri); }
internal const Int64 SHUTDOWN_TIMEOUT = 2000; /* miliseconds. */ internal TSIP_Dialog(tsip_dialog_type_t type, String callId, TSip_Session session) { mId = sUniqueId++; mRecordRoutes = new List <TSIP_HeaderRecordRoute>(); mChallenges = new List <TSIP_Challenge>(); mPaths = new List <TSIP_Uri>(); mServiceRoutes = new List <TSIP_Uri>(); mAssociatedUris = new List <TSIP_Uri>(); mState = tsip_dialog_state_t.Initial; mType = type; mCallId = String.IsNullOrEmpty(callId) ? TSIP_HeaderCallId.RandomCallId() : callId; mSipSession = session; /* Sets some default values */ mExpires = TSip_Session.DEFAULT_EXPIRES; mTagLocal = TSK_String.Random(); mCSeqValue = (UInt32) new Random().Next(); /*=== SIP Session ===*/ if (mSipSession != null) { mExpires = mSipSession.Expires; mUriLocal = !String.IsNullOrEmpty(callId) /* Server Side */ ? mSipSession.UriTo : mSipSession.UriFrom; if (mSipSession.UriTo != null) { mUriRemote = mSipSession.UriTo; mUriRemoteTarget = mSipSession.UriTo; } else { mUriRemote = mSipSession.UriFrom; mUriRemoteTarget = mSipSession.Stack.Realm; } } else { TSK_Debug.Error("Invalid Sip Session"); } }
internal static void TestUriParser() { int i; for (i = 0; i < __Uris.Length; i++) { TSIP_Uri uri = TSIP_ParserUri.Parse(__Uris[i]); TSK_Debug.Info("\n== Parsing {{ {0} }} ==\n", __Uris[i]); if (uri != null) { TSK_Debug.Info("scheme: {0}", uri.Scheme); TSK_Debug.Info("user-name: {0}", uri.UserName); TSK_Debug.Info("password: {0}", uri.Password); TSK_Debug.Info("host: {0}", uri.Host); TSK_Debug.Info("port: {0}", uri.Port); TSK_Debug.Info("host-type: {0}", uri.HostType == tsip_host_type_t.IPv4 ? "IPv4" : (uri.HostType == tsip_host_type_t.IPv6 ? "IPv6" : (uri.HostType == tsip_host_type_t.Hostname ? "HOSTNAME" : "UNKNOWN"))); TSK_Debug.Info("---PARAMS---"); /* dump all parameters */ foreach (TSK_Param param in uri.Params) { TSK_Debug.Info("-->{0}={1}", param.Name, param.Value); } TSK_Debug.Info("Is-secure: {0}", uri.IsSecure ? "YES" : "NO"); TestToString(uri); uri.Dispose(); } else { TSK_Debug.Error("INVALID SIP URI"); } TSK_Debug.Info("\n\n"); } }
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); }
/* #line 124 "./ragel/tsip_parser_uri.rl" */ public static TSIP_Uri Parse(String data) { if (String.IsNullOrEmpty(data)) { return(null); } int cs = 0; int p = 0; int pe = data.Length; int eof = pe; int ts = 0, te = 0; int act = 0; TSIP_Uri uri = TSIP_Uri.Create(tsip_uri_type_t.Unknown); int tag_start = 0; /* #line 395 "../Parsers/TSIP_ParserUri.cs" */ { cs = tsip_machine_parser_uri_start; ts = -1; te = -1; act = 0; } /* #line 145 "./ragel/tsip_parser_uri.rl" */ /* #line 405 "../Parsers/TSIP_ParserUri.cs" */ { sbyte _klen; short _trans; sbyte _acts; sbyte _nacts; short _keys; if (p == pe) { goto _test_eof; } if (cs == 0) { goto _out; } _resume: _acts = _tsip_machine_parser_uri_from_state_actions[cs]; _nacts = _tsip_machine_parser_uri_actions[_acts++]; while (_nacts-- > 0) { switch (_tsip_machine_parser_uri_actions[_acts++]) { case 12: /* #line 1 "./ragel/tsip_parser_uri.rl" */ { ts = p; } break; /* #line 426 "../Parsers/TSIP_ParserUri.cs" */ default: break; } } _keys = _tsip_machine_parser_uri_key_offsets[cs]; _trans = (short)_tsip_machine_parser_uri_index_offsets[cs]; _klen = _tsip_machine_parser_uri_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 (data[p] < _tsip_machine_parser_uri_trans_keys[_mid]) { _upper = (short)(_mid - 1); } else if (data[p] > _tsip_machine_parser_uri_trans_keys[_mid]) { _lower = (short)(_mid + 1); } else { _trans += (short)(_mid - _keys); goto _match; } } _keys += (short)_klen; _trans += (short)_klen; } _klen = _tsip_machine_parser_uri_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 (data[p] < _tsip_machine_parser_uri_trans_keys[_mid]) { _upper = (short)(_mid - 2); } else if (data[p] > _tsip_machine_parser_uri_trans_keys[_mid + 1]) { _lower = (short)(_mid + 2); } else { _trans += (short)((_mid - _keys) >> 1); goto _match; } } _trans += (short)_klen; } _match: _trans = (short)_tsip_machine_parser_uri_indicies[_trans]; _eof_trans: cs = _tsip_machine_parser_uri_trans_targs[_trans]; if (_tsip_machine_parser_uri_trans_actions[_trans] == 0) { goto _again; } _acts = _tsip_machine_parser_uri_trans_actions[_trans]; _nacts = _tsip_machine_parser_uri_actions[_acts++]; while (_nacts-- > 0) { switch (_tsip_machine_parser_uri_actions[_acts++]) { case 0: /* #line 36 "./ragel/tsip_parser_uri.rl" */ { tag_start = p; } break; case 1: /* #line 41 "./ragel/tsip_parser_uri.rl" */ { uri.Scheme = "sip"; uri.Type = tsip_uri_type_t.Sip; } break; case 2: /* #line 42 "./ragel/tsip_parser_uri.rl" */ { uri.Scheme = "sips"; uri.Type = tsip_uri_type_t.Sips; } break; case 3: /* #line 43 "./ragel/tsip_parser_uri.rl" */ { uri.Scheme = "tel"; uri.Type = tsip_uri_type_t.Tel; } break; case 4: /* #line 46 "./ragel/tsip_parser_uri.rl" */ { uri.HostType = tsip_host_type_t.IPv4; } break; case 5: /* #line 47 "./ragel/tsip_parser_uri.rl" */ { uri.HostType = tsip_host_type_t.IPv6; } break; case 6: /* #line 48 "./ragel/tsip_parser_uri.rl" */ { uri.HostType = tsip_host_type_t.Hostname; } break; case 7: /* #line 54 "./ragel/tsip_parser_uri.rl" */ { uri.UserName = TSK_RagelState.Parser.GetString(data, p, tag_start); } break; case 8: /* #line 58 "./ragel/tsip_parser_uri.rl" */ { uri.Password = TSK_RagelState.Parser.GetString(data, p, tag_start); } break; case 9: /* #line 70 "./ragel/tsip_parser_uri.rl" */ { TSK_Param param = TSK_RagelState.Parser.GetParam(data, p, tag_start); if (param != null) { uri.Params.Add(param); } } break; case 10: /* #line 84 "./ragel/tsip_parser_uri.rl" */ { { cs = 26; if (true) { goto _again; } } } break; case 13: /* #line 1 "./ragel/tsip_parser_uri.rl" */ { te = p + 1; } break; case 14: /* #line 97 "./ragel/tsip_parser_uri.rl" */ { te = p + 1; { uri.Host = TSK_RagelState.Scanner.GetString(data, ts, te); if (uri.HostType == tsip_host_type_t.IPv6) { uri.Host = TSK_String.UnQuote(uri.Host, '[', ']'); } } } break; case 15: /* #line 88 "./ragel/tsip_parser_uri.rl" */ { te = p; p--; { if (TSK_String.Contains(data.Substring(te), (pe - te), "@")) { { cs = 18; if (true) { goto _again; } } } } } break; case 16: /* #line 94 "./ragel/tsip_parser_uri.rl" */ { te = p; p--; { } } break; case 17: /* #line 97 "./ragel/tsip_parser_uri.rl" */ { te = p; p--; { uri.Host = TSK_RagelState.Scanner.GetString(data, ts, te); if (uri.HostType == tsip_host_type_t.IPv6) { uri.Host = TSK_String.UnQuote(uri.Host, '[', ']'); } } } break; case 18: /* #line 105 "./ragel/tsip_parser_uri.rl" */ { te = p; p--; { ts++; uri.Port = (ushort)TSK_RagelState.Scanner.GetInt32(data, ts, te); } } break; case 19: /* #line 110 "./ragel/tsip_parser_uri.rl" */ { te = p; p--; { } } break; case 20: /* #line 111 "./ragel/tsip_parser_uri.rl" */ { te = p; p--; { } } break; case 21: /* #line 94 "./ragel/tsip_parser_uri.rl" */ { { p = ((te)) - 1; } { } } break; case 22: /* #line 97 "./ragel/tsip_parser_uri.rl" */ { { p = ((te)) - 1; } { uri.Host = TSK_RagelState.Scanner.GetString(data, ts, te); if (uri.HostType == tsip_host_type_t.IPv6) { uri.Host = TSK_String.UnQuote(uri.Host, '[', ']'); } } } break; case 23: /* #line 110 "./ragel/tsip_parser_uri.rl" */ { { p = ((te)) - 1; } { } } break; /* #line 615 "../Parsers/TSIP_ParserUri.cs" */ default: break; } } _again: _acts = _tsip_machine_parser_uri_to_state_actions[cs]; _nacts = _tsip_machine_parser_uri_actions[_acts++]; while (_nacts-- > 0) { switch (_tsip_machine_parser_uri_actions[_acts++]) { case 11: /* #line 1 "./ragel/tsip_parser_uri.rl" */ { ts = -1; } break; /* #line 629 "../Parsers/TSIP_ParserUri.cs" */ default: break; } } if (cs == 0) { goto _out; } if (++p != pe) { goto _resume; } _test_eof : {} if (p == eof) { if (_tsip_machine_parser_uri_eof_trans[cs] > 0) { _trans = (short)(_tsip_machine_parser_uri_eof_trans[cs] - 1); goto _eof_trans; } } _out : {} } /* #line 146 "./ragel/tsip_parser_uri.rl" */ if (cs < /* #line 653 "../Parsers/TSIP_ParserUri.cs" */ 26 /* #line 147 "./ragel/tsip_parser_uri.rl" */ ) { TSK_Debug.Error("Failed to parse SIP/SIPS/TEL URI"); uri.Dispose(); return(null); } return(uri); }
static void Main(string[] args) { //Test_FSM.DefaultTest(); //TSIP_TransportUDP transportUdp = new TSIP_TransportUDP("192.168.0.13", TNET_Socket.TNET_SOCKET_PORT_ANY, false, "Sip Tansport using UDP"); //IPEndPoint remoteEP = TNET_Socket.CreateEndPoint("192.168.0.10", 5060); // Int32 count = transportUdp.SendTo(remoteEP, Encoding.UTF8.GetBytes("test")); //Test_UriParser.TestUriParser(); //Test_UriParser.TestMessageParser(); /*List<TSIP_HeaderVia> headers = TSIP_HeaderVia.Parse("Via: SIP/2.0/tcp 127.0.0.1:5082;branch=z9hG4bKc16be5aee32df400d01015675ab911ba,SIP/2.0/udp 127.0.0.1:5082;branch=z9hG4bKeec53b25db240bec92ea250964b8c1fa;received_port_ext=5081;received=192.168.0.13,SIP/2.0/UDP 192.168.0.12:57121;rport=57121;branch=z9hG4bK1274980921982;received_port_ext=5081;received=192.168.0.12\r\n"); * foreach (TSIP_HeaderVia h in headers) * { * Console.WriteLine(h.ToString(true, true, true)); * }*/ //TSIP_HeaderTo header = TSIP_HeaderTo.Parse("t: <sip:[email protected]>;tag= 12345\r\n"); //if (header != null) //{ // Console.WriteLine(header.ToString(true, true, true)); //} TSIP_Stack sipStack = new TSIP_Stack( TSIP_Uri.Create("sip:doubango.org"), "004", TSIP_Uri.Create("sip:[email protected]"), "192.168.0.10", 5060 ); sipStack.LocalIP = "192.168.0.13";//FIXME sipStack.Callback = delegate(TSIP_Event @event) { switch (@event.Type) { case TSIP_Event.tsip_event_type_t.DIALOG: { TSIP_EventDialog eventDialog = (@event as TSIP_EventDialog); break; } case TSIP_Event.tsip_event_type_t.REGISTER: { TSIP_EventRegister eventDialog = (@event as TSIP_EventRegister); break; } default: { return(false); } } return(true); }; if (sipStack.Start()) { TSIP_SessionRegister register = new TSIP_SessionRegister(sipStack); register.Register(); } Console.ReadLine(); }
internal static void TestToString(TSIP_Uri uri) { TSK_Debug.Info("uri_to_string={0}", uri); }
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); }
protected Int64 GetNewDelay(TSIP_Response response) { Int64 expires = mExpires; Int64 newdelay = expires; /* default value */ TSIP_Header hdr; int i; /*== NOTIFY with subscription-state header with expires parameter */ if (response.CSeq.RequestType == TSIP_Message.tsip_request_type_t.NOTIFY) { TSIP_HeaderSubscriptionState hdr_state = response.GetHeader(TSIP_Header.tsip_header_type_t.Subscription_State) as TSIP_HeaderSubscriptionState; if (hdr_state != null && hdr_state.Expires > 0) { expires = TSK_Time.Seconds2Milliseconds(hdr_state.Expires); goto compute; } } /*== Expires header */ if ((hdr = response.GetHeader(TSIP_Header.tsip_header_type_t.Expires)) != null) { expires = TSK_Time.Seconds2Milliseconds((hdr as TSIP_HeaderExpires).DeltaSeconds); goto compute; } /*== Contact header */ for (i = 0; (hdr = response.GetHeaderAtIndex(TSIP_Header.tsip_header_type_t.Contact, i)) != null; i++) { TSIP_HeaderContact contact = hdr as TSIP_HeaderContact; if (contact != null && contact.Uri != null) { String transport = TSK_Param.GetValueByName(contact.Uri.Params, "transport"); TSIP_Uri contactUri = this.Stack.GetContactUri(String.IsNullOrEmpty(transport) ? "udp" : transport); if (contactUri != null) { if (String.Equals(contact.Uri.UserName, contactUri.UserName) && String.Equals(contact.Uri.Host, contactUri.Host) && contact.Uri.Port == contactUri.Port) { if (contact.Expires >= 0) /* No expires parameter ==> -1*/ { expires = TSK_Time.Seconds2Milliseconds(contact.Expires); goto compute; } } } } } /* * 3GPP TS 24.229 - * * The UE shall reregister the public user identity either 600 seconds before the expiration time if the initial * registration was for greater than 1200 seconds, or when half of the time has expired if the initial registration * was for 1200 seconds or less. */ compute: expires = TSK_Time.Milliseconds2Seconds(expires); newdelay = (expires > 1200) ? (expires - 600) : (expires / 2); return(TSK_Time.Seconds2Milliseconds(newdelay)); }
/// <summary> /// Updates the dialog state: /// - Authorizations (using challenges from the @a response message) /// - State (early, established, disconnected, ...) /// - Routes (and Service-Route) /// - Target (remote) /// - ... /// </summary> /// <param name="response"></param> /// <returns></returns> protected Boolean UpdateWithResponse(TSIP_Response response) { if (response == null || response.To == null || response.CSeq == null) { return(false); } String tag = response.To.Tag; /* * 1xx (!100) or 2xx */ /* * 401 or 407 or 421 or 494 */ if (response.StatusCode == 401 || response.StatusCode == 407 || response.StatusCode == 421 || response.StatusCode == 494) { Boolean acceptNewVector; /* 3GPP IMS - Each authentication vector is used only once. * ==> Re-registration/De-registration ==> Allow 401/407 challenge. */ acceptNewVector = (response.CSeq.RequestType == TSIP_Message.tsip_request_type_t.REGISTER && this.State == tsip_dialog_state_t.Established); return(this.UpdateChallenges(response, acceptNewVector)); } else if (100 < response.StatusCode && response.StatusCode < 300) { tsip_dialog_state_t state = this.State; /* 1xx */ if (response.StatusCode <= 199) { if (String.IsNullOrEmpty(response.To.Tag)) { TSK_Debug.Error("Invalid tag parameter"); return(false); } state = tsip_dialog_state_t.Early; } /* 2xx */ else { state = tsip_dialog_state_t.Established; } /* Remote target */ { /* RFC 3261 12.2.1.2 Processing the Responses * When a UAC receives a 2xx response to a target refresh request, it * MUST replace the dialog's remote target URI with the URI from the * Contact header field in that response, if present. * * FIXME: Because PRACK/UPDATE sent before the session is established MUST have * the rigth target URI to be delivered to the UAS ==> Do not not check that we are connected */ if (response.CSeq.RequestType != TSIP_Message.tsip_request_type_t.REGISTER && response.Contact != null && response.Contact.Uri != null) { mUriRemoteTarget = response.Contact.Uri.Clone(true, false); } } /* Route sets */ { int index; TSIP_HeaderRecordRoute recordRoute; mRecordRoutes.Clear(); for (index = 0; (recordRoute = response.GetHeaderAtIndex(TSIP_Header.tsip_header_type_t.Record_Route, index) as TSIP_HeaderRecordRoute) != null; index++) { mRecordRoutes.Insert(0, recordRoute); /* Copy reversed. */ } } /* cseq + tags + ... */ if (this.State == tsip_dialog_state_t.Established && String.Equals(mTagRemote, tag, StringComparison.InvariantCultureIgnoreCase)) { return(true); } else { if (response.CSeq.RequestType != TSIP_Message.tsip_request_type_t.REGISTER && response.CSeq.RequestType != TSIP_Message.tsip_request_type_t.PUBLISH) { /* REGISTER and PUBLISH don't establish dialog */ mTagRemote = tag; } #if NEVER_EXECUTE_00 // PRACK and BYE will have same CSeq value ==> Let CSeq value to be incremented by "tsip_dialog_request_new()" self->cseq_value = response->CSeq ? response->CSeq->seq : self->cseq_value; #endif } this.State = state; return(true); } return(true); }
// Constructor public MainPage() { InitializeComponent(); String mm = "SIP/2.0 200 OK\r\n" + "Via: SIP/2.0/UDP 192.168.0.13:5060;branch=z9hG4bK_56ef1cda-aef6-4d76-ab7e-d148af3b18ac;rport=51049\r\n" + "Record-Route: <sip:192.168.0.10:5060;lr;transport=udp>\r\n" + "To: <sip:[email protected]>\r\n" + "From: <sip:[email protected]>;tag=9bff9c34-35e3-4fa8-8de4-290ce275c981\r\n" + "Call-ID: 272b67b9-08b2-4fce-8f6e-6ccaf5e5ec9a\r\n" + "CSeq: 1990525622 REGISTER\r\n" + "Server: mjsip stack 1.6\r\n" + "Contact: <sip:[email protected]:5060>;expires=10\r\n" + "Content-Length: 0\r\n" + "\r\n"; /*TSIP_Message message = TSIP_ParserMessage.Parse(UTF8Encoding.UTF8.GetBytes(mm), true); * if (message != null) * { * }*/ TSIP_Stack sipStack = new TSIP_Stack( TSIP_Uri.Create("sip:doubango.org"), "004", TSIP_Uri.Create("sip:[email protected]"), "192.168.0.10", 5060 ); // sipStack.Headers.Add(new TSK_Param("User-Agent", "wp-ngn-stack")); sipStack.AoRIP = "192.168.0.13"; sipStack.AoRPort = 5060; sipStack.Callback = delegate(TSIP_Event @event) { switch (@event.Type) { case TSIP_Event.tsip_event_type_t.DIALOG: { TSIP_EventDialog eventDialog = (@event as TSIP_EventDialog); break; } case TSIP_Event.tsip_event_type_t.REGISTER: { TSIP_EventRegister eventDialog = (@event as TSIP_EventRegister); break; } default: { return(false); } } return(true); }; if (sipStack.Start()) { TSIP_SessionRegister register = new TSIP_SessionRegister(sipStack); register.Register(); } }
public TSIP_HeaderRecordRoute(TSIP_Uri uri) : base(tsip_header_type_t.Record_Route) { mUri = uri; }
public TSIP_HeaderRoute(TSIP_Uri uri) : base(tsip_header_type_t.Record_Route) { mUri = uri; }