/// <summary> /// Adds or updates matching bindings. /// </summary> /// <param name="flow">SIP data flow what updates this binding. This value is null if binding was not added through network or /// flow has disposed.</param> /// <param name="callID">Call-ID header field value.</param> /// <param name="cseqNo">CSeq header field sequence number value.</param> /// <param name="contacts">Contacts to add or update.</param> /// <exception cref="ArgumentNullException">Is raised when <b>callID</b> or <b>contacts</b> is null reference.</exception> public void AddOrUpdateBindings(SIP_Flow flow,string callID,int cseqNo,SIP_t_ContactParam[] contacts) { if(callID == null){ throw new ArgumentNullException("callID"); } if(cseqNo < 0){ throw new ArgumentException("Argument 'cseqNo' value must be >= 0."); } if(contacts == null){ throw new ArgumentNullException("contacts"); } lock(m_pLock){ foreach(SIP_t_ContactParam contact in contacts){ SIP_RegistrationBinding binding = GetBinding(contact.Address.Uri); // Add binding. if(binding == null){ binding = new SIP_RegistrationBinding(this,contact.Address.Uri); m_pBindings.Add(binding); } // Update binding. binding.Update( flow, contact.Expires == -1 ? 3600 : contact.Expires, contact.QValue == -1 ? 1.0 : contact.QValue, callID, cseqNo ); } } }
/// <summary> /// Refreshes specified registration info. /// </summary> public void Refresh() { /* GetSipRegistration "<virtualServerID>" "<addressOfRecord>" Responses: +OK <sizeOfData> <data> -ERR <errorText> */ lock(m_pOwner.VirtualServer.Server.LockSynchronizer){ m_pOwner.VirtualServer.Server.TcpClient.TcpStream.WriteLine("GetSipRegistration " + TextUtils.QuoteString(m_pOwner.VirtualServer.VirtualServerID) + " " + TextUtils.QuoteString(m_AddressOfRecord) ); string response = m_pOwner.VirtualServer.Server.ReadLine(); if(!response.ToUpper().StartsWith("+OK")){ throw new Exception(response); } int sizeOfData = Convert.ToInt32(response.Split(new char[]{' '},2)[1]); MemoryStream ms = new MemoryStream(); m_pOwner.VirtualServer.Server.TcpClient.TcpStream.ReadFixedCount(ms,sizeOfData); // Decompress dataset DataSet ds = Utils.DecompressDataSet(ms); if(ds.Tables.Contains("Contacts")){ List<SipRegistrationContact> contacts = new List<SipRegistrationContact>(); foreach(DataRow dr in ds.Tables["Contacts"].Rows){ SIP_t_ContactParam c = new SIP_t_ContactParam(); c.Parse(new LumiSoft.Net.StringReader(dr["Value"].ToString())); contacts.Add(new SipRegistrationContact(c.Address.Uri.Value,c.Expires,c.QValue)); } m_pContacts = contacts.ToArray(); } else{ m_pContacts = new SipRegistrationContact[0]; } } }
/// <summary> /// Gets server events and binds them to this. /// </summary> private void Bind() { /* GetSipRegistrations "<virtualServerID>" Responses: +OK <sizeOfData> <data> -ERR <errorText> */ lock(m_pOwner.Server.LockSynchronizer){ m_pOwner.Server.Socket.WriteLine("GetSipRegistrations " + TextUtils.QuoteString(m_pOwner.VirtualServerID) ); string response = m_pOwner.Server.Socket.ReadLine(); if(!response.ToUpper().StartsWith("+OK")){ throw new Exception(response); } int sizeOfData = Convert.ToInt32(response.Split(new char[]{' '},2)[1]); MemoryStream ms = new MemoryStream(); m_pOwner.Server.Socket.ReadSpecifiedLength(sizeOfData,ms); // Decompress dataset DataSet ds = Utils.DecompressDataSet(ms); if(ds.Tables.Contains("SipRegistrations")){ foreach(DataRow dr in ds.Tables["SipRegistrations"].Rows){ //--- Parse contact -------------------------------------------------------------// List<SipRegistrationContact> contacts = new List<SipRegistrationContact>(); foreach(string contact in dr["Contacts"].ToString().Split('\t')){ if(!string.IsNullOrEmpty(contact)){ SIP_t_ContactParam c = new SIP_t_ContactParam(); c.Parse(new LumiSoft.Net.StringReader(contact)); contacts.Add(new SipRegistrationContact(c.Address.Uri,c.Expires,c.QValue)); } } //--------------------------------------------------------------------------------// m_pRegistrations.Add(new SipRegistration( this, dr["UserName"].ToString(), dr["AddressOfRecord"].ToString(), contacts.ToArray() )); } } } }
/// <summary> /// Converts <b>ContactUri</b> to valid Contact header value. /// </summary> /// <returns>Returns contact header value.</returns> public string ToContactValue() { SIP_t_ContactParam retVal = new SIP_t_ContactParam(); retVal.Parse(new StringReader(m_ContactURI.ToString())); retVal.Expires = m_Expires; return retVal.ToStringValue(); }
/// <summary> /// Add or updates specified SIP registration info. /// </summary> /// <param name="aor">Registration address of record.</param> /// <param name="contacts">Registration address of record contacts to update.</param> /// <param name="flow">SIP proxy local data flow what accpeted this contact registration.</param> public void SetRegistration(string aor,SIP_t_ContactParam[] contacts,SIP_Flow flow) { lock(m_pRegistrations){ SIP_Registration registration = m_pRegistrations[aor]; if(registration == null){ registration = new SIP_Registration("system",aor); m_pRegistrations.Add(registration); OnAorRegistered(registration); } registration.AddOrUpdateBindings(flow,"",1,contacts); } }
/// <summary> /// Add or updates specified SIP registration info. /// </summary> /// <param name="aor">Registration address of record.</param> /// <param name="contacts">Registration address of record contacts to update.</param> public void SetRegistration(string aor,SIP_t_ContactParam[] contacts) { SetRegistration(aor,contacts,null); }
/// <summary> /// Redirects incoming call to speified contact(s). /// </summary> /// <param name="contacts">Redirection targets.</param> /// <exception cref="ObjectDisposedException">Is raised when this object is disposed and and this method is accessed.</exception> /// <exception cref="InvalidOperationException">Is raised when call is not in valid state and this method is called.</exception> /// <exception cref="ArgumentNullException">Is raised when <b>contacts</b> is null.</exception> /// <exception cref="ArgumentException">Is raised when any of the arguments has invalid value.</exception> public void Redirect(SIP_t_ContactParam[] contacts) { lock(m_pLock){ if(this.State == SIP_UA_CallState.Disposed){ throw new ObjectDisposedException(this.GetType().Name); } if(this.State != SIP_UA_CallState.WaitingToAccept){ throw new InvalidOperationException("Call is not in valid state."); } if(contacts == null){ throw new ArgumentNullException("contacts"); } if(contacts.Length == 0){ throw new ArgumentException("Arguments 'contacts' must contain at least 1 value."); } // TODO: //m_pUA.Stack.CreateResponse(SIP_ResponseCodes.,m_pInitialInviteTransaction); throw new NotImplementedException(); } }
/// <summary> /// Updates registration contacts. /// </summary> /// <param name="contacts">SIP contacts to add/update.</param> /// <param name="expires">This is register request header field Expires: value and used only if contact doesn't have expires parameter.</param> /// <param name="minExpires">SIP server minimum expire time in seconds.</param> /// <param name="localEP">SIP proxy local end point info what accpeted this contact registration.</param> public void UpdateContacts(SIP_t_ContactParam[] contacts,int expires,int minExpires,SIP_EndPointInfo localEP) { lock(m_pContacts){ foreach(SIP_t_ContactParam contact in contacts){ // Handle special value STAR Contact:, this means that we need to remove all contacts. if(contact.IsStarContact){ m_pContacts.Clear(); return; } SIP_RegistrationContact currentContact = GetContact(contact.Address.Uri); // Get contact expire time. int contactExpires = contact.Expires; if(contactExpires == -1){ contactExpires = expires; } if(contactExpires == -1){ contactExpires = minExpires; } // Remove specified contact if(contactExpires == 0){ if(currentContact != null){ m_pContacts.Remove(currentContact); } } // Add else if(currentContact == null){ m_pContacts.Add(new SIP_RegistrationContact(contact,contactExpires,localEP)); } // Update else{ currentContact.UpdateContact(contact,contactExpires,localEP); } } } }
private void SetSipRegistration(string argsText) { /* SetSipRegistration "<virtualServerID>" "<addressOfRecord>" "<contacts>" Responses: +OK -ERR <errorText> */ try{ string[] args = TextUtils.SplitQuotedString(argsText,' ',true); if(args.Length != 3){ WriteLine("-ERR Invalid arguments. Syntax: SetSipRegistration \"<virtualServerID>\" \"<addressOfRecord>\" \"<contacts>\""); return; } foreach(VirtualServer virtualServer in this.Server.MailServer.VirtualServers){ if(virtualServer.ID.ToLower() == args[0].ToLower()){ List<SIP_t_ContactParam> contacts = new List<SIP_t_ContactParam>(); foreach(string contact in args[2].Split('\t')){ if(contact.Length > 0){ SIP_t_ContactParam c = new SIP_t_ContactParam(); c.Parse(new LumiSoft.Net.StringReader(contact)); contacts.Add(c); } } virtualServer.SipServer.Registrar.SetRegistration(args[1],contacts.ToArray()); WriteLine("+OK"); return; } } WriteLine("-ERR Specified virtual server with ID '" + argsText + "' doesn't exist !"); } catch(Exception x){ WriteLine("-ERR " + x.Message); } }
/// <summary> /// Default constructor. /// </summary> /// <param name="contact">SIP contact.</param> /// <param name="expires">Time in seconds when contact expires.</param> /// <param name="localEP">SIP proxy local end point info what accpeted this contact registration.</param> public SIP_RegistrationContact(SIP_t_ContactParam contact,int expires,SIP_EndPointInfo localEP) { UpdateContact(contact,expires,localEP); }
/// <summary> /// Updates contact info. /// </summary> /// <param name="contact">SIP contact.</param> /// <param name="expires">Time in seconds when contact expires.</param> /// <param name="localEP">SIP proxy local end point info what accpeted this contact registration.</param> public void UpdateContact(SIP_t_ContactParam contact,int expires,SIP_EndPointInfo localEP) { m_pContact = contact; m_Expire = expires; m_pLocalEndPoint = localEP; m_LastUpdate = DateTime.Now; }
/// <summary> /// Returns this.Contact as string value, but expires parameter is replaced with remaining time value. /// </summary> /// <returns></returns> public string ToStringValue() { SIP_t_ContactParam retVal = new SIP_t_ContactParam(); retVal.Parse(new StringReader(m_pContact.ToStringValue())); retVal.Expires = this.Expires; return retVal.ToStringValue(); }