Example #1
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="localEP">Local end point to use to connect remote destination.</param>
        /// <param name="destination">Remote destination URI.</param>
        public SIP_Target(SIP_EndPointInfo localEP,SIP_Uri destination)
        {
            m_pLocalEndPoint = localEP;

            if(destination.Param_Transport != null){
                m_Transport = destination.Param_Transport;
            }
            else{
                // If SIPS, use always TLS.
                if(destination.IsSecure){
                    m_Transport = SIP_Transport.TLS;
                }
                else{
                    m_Transport = SIP_Transport.UDP;
                }
            }
            m_Host = destination.Host;
            if(destination.Port != -1){
                m_Port = destination.Port;
            }
            else{
                if(m_Transport == SIP_Transport.TLS){
                    m_Port = 5061;
                }
                else{
                    m_Port = 5060;
                }
            }
        }
        /// <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);
                    }
                }
            }
        }
 /// <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>
 /// 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>
        /// Sends specified request to specified SIP server.
        /// </summary>
        /// <param name="request">SIP request to send.</param>
        /// <param name="localEndPoint">Local end point to use. Value null means first available. NOTE: This is used only if transport = UDP.</param>
        /// <param name="remoteEndPoint">Destination remote endpoint where to send request.</param>
        /// <param name="transport">SIP transport to use. Supported values are defined in SIP_Transport class.</param>
        /// <exception cref="SIP_TransportException">Is raised when sending fails.</exception>
        public void SendRequest(SIP_Request request,SIP_EndPointInfo localEndPoint,IPEndPoint remoteEndPoint,string transport)
        {
            /* RFC 3561 18.1.1 Sending Requests.
                The client side of the transport layer is responsible for sending the
                request and receiving responses.  The user of the transport layer
                passes the client transport the request, an IP address, port,
                transport, and possibly TTL for multicast destinations.

                A client that sends a request to a multicast address MUST add the
                "maddr" parameter to its Via header field value containing the
                destination multicast address, and for IPv4, SHOULD add the "ttl"
                parameter with a value of 1.

                Before a request is sent, the client transport MUST insert a value of
                the "sent-by" field into the Via header field.  This field contains
                an IP address or host name, and port.  The usage of an FQDN is RECOMMENDED.

                For reliable transports, the response is normally sent on the
                connection on which the request was received.  Therefore, the client
                transport MUST be prepared to receive the response on the same
                connection used to send the request.

                For unreliable unicast transports, the client transport MUST be
                prepared to receive responses on the source IP address from which the request is sent.

                For multicast, the client transport MUST be prepared to receive
                responses on the same multicast group and port to which the request is sent.
            */

            try{
                byte[]        data = null;
                SipTcpPipe    pipe = null;
                SIP_t_ViaParm via  = request.Via.GetTopMostValue();

                /*
                    If UDP or TCP we always can override "transport" to reuse any existing TCP/TLS connection.
                    If TLS we can reuse only existing TLS connection.
                */
                if(transport.ToUpper() == SIP_Transport.UDP || transport.ToUpper() == SIP_Transport.TCP){
                    pipe = GetTcpPipe(null,remoteEndPoint);
                    // Not existing connection.
                    if(pipe == null){
                        // Not existing connection, create it.
                        if(transport == SIP_Transport.TCP){
                            pipe = new SipTcpPipe(this,remoteEndPoint,false);
                        }
                        // Use UDP socket.
                        else{
                            foreach(SipListeningPoint listeningPoint in m_pListeningPoints){
                                if(listeningPoint.Protocol == BindInfoProtocol.UDP){
                                    if(localEndPoint == null || listeningPoint.LocalEndPoint.Equals(localEndPoint.EndPoint)){
                                        // Set sent-by value.
                                        if(!string.IsNullOrEmpty(m_pSipStack.HostName)){
                                            via.SentBy = m_pSipStack.HostName;
                                        }
                                        else if(pipe.LocalEndPoint.Address.Equals(IPAddress.Any)){
                                            // Get first IP
                                            via.SentBy = System.Net.Dns.GetHostAddresses("")[0] + ":" + pipe.LocalEndPoint.Port;
                                        }
                                        else{
                                            via.SentBy = listeningPoint.LocalEndPoint.ToString();
                                        }

                                        data = request.ToByteData();

                                        // Log
                                        m_pSipStack.Logger.AddWrite(data.Length,"Sending (" + data.Length + " bytes): " + listeningPoint.LocalEndPoint.ToString() + " -> " + remoteEndPoint.ToString() + "\r\n<begin>\r\n" + System.Text.Encoding.UTF8.GetString(data) + "<end>\r\n");

                                        listeningPoint.Socket.SendTo(data,remoteEndPoint);
                                        return;
                                    }
                                }
                            }

                            throw new SIP_TransportException("No suitable UDP socket !");
                        }
                    }
                    // We can reuse existing connection, use it.
                    // We stored pipe, we use it later.
                    //else{
                    //}
                }
                else if(transport.ToUpper() == SIP_Transport.TLS){
                    pipe = GetTcpPipe(SIP_Transport.TLS,remoteEndPoint);
                    // Not existing connection, create it.
                    if(pipe == null){
                        pipe = new SipTcpPipe(this,remoteEndPoint,true);
                    }
                }
                else{
                    throw new SIP_TransportException("No transport for protocol '" + transport + "' !");
                }

                // Set sent-by value.
                if(!string.IsNullOrEmpty(m_pSipStack.HostName)){
                    via.SentBy = m_pSipStack.HostName;
                }
                else if(pipe.LocalEndPoint.Address.Equals(IPAddress.Any)){
                    // Get first IP
                    via.SentBy = System.Net.Dns.GetHostAddresses("")[0] + ":" + pipe.LocalEndPoint.Port;
                }
                else{
                    via.SentBy = pipe.LocalEndPoint.ToString();
                }

                data = request.ToByteData();

                // Log
                m_pSipStack.Logger.AddWrite(data.Length,"Sending (" + data.Length + " bytes): " + pipe.LocalEndPoint.ToString() + " -> " + remoteEndPoint.ToString() + "\r\n<begin>\r\n" + System.Text.Encoding.UTF8.GetString(data) + "<end>\r\n");

                // Send request.
                pipe.SendMessage(data);
            }
            catch(Exception x){
                throw new SIP_TransportException(x.Message);
            }
        }