Ejemplo n.º 1
0
        private Boolean AddAoRToMessage(TSIP_Message msg)
        {
            if (!msg.ShouldUpdate)
            {
                return(true);
            }

            /* retrieves the transport ip address and port */
            if (String.IsNullOrEmpty(mStack.AoRIP) && mStack.AoRPort <= 0)
            {
                String ip;
                ushort port;
                if (!GetLocalIpAndPort(out ip, out port))
                {
                    return(false);
                }
                else
                {
                    mStack.AoRIP   = ip;
                    mStack.AoRPort = port;
                }
            }

            /* === Host and port === */
            if (msg.Contact != null && msg.Contact.Uri != null)
            {
                msg.Contact.Uri.Scheme = this.Scheme;
                msg.Contact.Uri.Host   = mStack.AoRIP;
                msg.Contact.Uri.Port   = mStack.AoRPort;
            }

            return(true);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Trying -> (200-699) -> Completed
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean Trying_2_Completed_X_200_to_699(params Object[] parameters)
        {
            TSIP_Message message = parameters[1] as TSIP_Message;

            /*	RFC 3261 - 17.1.2.2
             *      If a final response (status codes 200-699) is received while in the "Trying" state, the response
             *      MUST be passed to the TU, and the client transaction MUST transition
             *      to the "Completed" state.
             *
             *      If Timer K fires while in this state (Completed), the client transaction MUST transition to the "Terminated" state.
             */

            if (!base.Reliable)
            {
                this.TimerE.Stop();
            }
            this.TimerF.Stop();

            Boolean ret = base.Dialog.RaiseCallback(TSIP_Dialog.tsip_dialog_event_type_t.I_MSG, message);

            /* SCHEDULE timer K */
            this.TimerK.Start();

            return(ret);
        }
/* #line 150 "./ragel/tsip_parser_message.rl" */

    public static TSIP_Message Parse(byte[] content, Boolean extractContent)
    {
        TSK_RagelState state = TSK_RagelState.Init(content);

        byte[]       data    = content;
        TSIP_Message message = null;

        // Ragel init
        TSIP_ParserMessage.Init(ref state);

        // State mechine execution
        message = TSIP_ParserMessage.Execute(ref state, extractContent);

        // Check result
        if (message != null && state.CS <
/* #line 196 "../Parsers/TSIP_ParserMessage.cs" */
            37
/* #line 164 "./ragel/tsip_parser_message.rl" */
            )
        {
            message.Dispose();
            message = null;
        }
        return(message);
    }
Ejemplo n.º 4
0
        /// <summary>
        /// Proceeding -> (200-699) -> Completed
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean Proceeding_2_Completed_X_200_to_699(params Object[] parameters)
        {
            TSIP_Message message = parameters[1] as TSIP_Message;

            /*	RFC 3261 - 17.1.2.2
             *      If a final response (status codes 200-699) is received while in the
             *      "Proceeding" state, the response MUST be passed to the TU, and the
             *      client transaction MUST transition to the "Completed" state.
             */

            /*	RFC 3261 - 17.1.2.2
             *      Once the client transaction enters the "Completed" state, it MUST set
             *      Timer K to fire in T4 seconds for unreliable transports, and zero
             *      seconds for reliable transports.  The "Completed" state exists to
             *      buffer any additional response retransmissions that may be received
             *      (which is why the client transaction remains there only for
             *
             *      unreliable transports).  T4 represents the amount of time the network
             *      will take to clear messages between client and server transactions.
             *      The default value of T4 is 5s.
             */

            if (!base.Reliable)
            {
                this.TimerE.Stop();
            }

            if (base.Dialog.RaiseCallback(TSIP_Dialog.tsip_dialog_event_type_t.I_MSG, message))
            {
                /* SCHEDULE timer K */
                return(this.TimerK.Start());
            }
            return(false);
        }
Ejemplo n.º 5
0
 internal Boolean RaiseCallback(tsip_dialog_event_type_t type, TSIP_Message message)
 {
     if (mCallback != null)
     {
         return(mCallback(type, message));
     }
     return(false);
 }
Ejemplo n.º 6
0
 internal Boolean RaiseCallback(tsip_transac_event_type_t type, TSIP_Message message)
 {
     if (this.Callback != null)
     {
         return(this.Callback(type, message));
     }
     return(false);
 }
Ejemplo n.º 7
0
        internal static void TestMessageParser()
        {
            TSIP_Message message = TSIP_ParserMessage.Parse(Encoding.UTF8.GetBytes(SIP_MESSAGE), true);

            if (message != null)
            {
                TSK_Debug.Info("Request = {0}", message);
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Proceeding -> (1xx) -> Proceeding
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean Proceeding_2_Proceeding_X_1xx(params Object[] parameters)
        {
            TSIP_Message message = parameters[1] as TSIP_Message;

            if (!base.Reliable)
            {
                this.TimerE.Stop();
            }
            return(base.Dialog.RaiseCallback(TSIP_Dialog.tsip_dialog_event_type_t.I_MSG, message));
        }
Ejemplo n.º 9
0
        public Boolean ExecuteAction(Int32 fsmActionId, TSIP_Message message, TSIP_Action action)
        {
            if (this.StateMachine != null)
            {
                return(this.StateMachine.ExecuteAction(fsmActionId, this, message, this, message, action));
            }

            TSK_Debug.Error("Invalid FSM");

            return(false);
        }
Ejemplo n.º 10
0
        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 Boolean SendMessage(String branch, TSIP_Message message)
        {
            String destIP   = null;
            ushort destPort = 5060;

            TSIP_Transport transport = this.FindTransport(message, out destIP, out destPort);

            if (transport != null)
            {
                return(transport.Send(branch, message, destIP, destPort));
            }

            return(false);
        }
        private Boolean HandleIncomingMessage(TSIP_Message message)
        {
            Boolean ret = false;

            if (message != null)
            {
                if (!(ret = mStack.LayerTransac.HandleIncomingMsg(message)))
                {
                    /* NO MATCHING TRANSACTION FOUND ==> LOOK INTO DIALOG LAYER */
                    ret = mStack.LayerDialog.HandleIncomingMessage(message);
                }
            }
            return(ret);
        }
Ejemplo n.º 13
0
        private Boolean OnCallbackEvent(tsip_transac_event_type_t type, TSIP_Message message)
        {
            Boolean ret = true;

            switch (type)
            {
            case tsip_transac_event_type_t.IncomingMessage:
            {
                if (message != null && message.IsResponse)
                {
                    if ((message as TSIP_Response).Is1xx)
                    {
                        ret = base.ExecuteAction((Int32)FSMAction._1xx, message);
                    }
                    else if ((message as TSIP_Response).Is23456)
                    {
                        ret = base.ExecuteAction((Int32)FSMAction._200_to_699, message);
                    }
                    else
                    {
                        TSK_Debug.Error("Not supported status code: {0}", (message as TSIP_Response).StatusCode);
                    }
                }
                break;
            }

            case tsip_transac_event_type_t.Canceled:
            case tsip_transac_event_type_t.Terminated:
            case tsip_transac_event_type_t.TimedOut:
            default:
            {
                break;
            }

            case tsip_transac_event_type_t.Error:
            {
                ret = base.ExecuteAction((Int32)FSMAction.Error, message);
                break;
            }

            case tsip_transac_event_type_t.TransportError:
            {
                ret = base.ExecuteAction((Int32)FSMAction.TransportError, message);
                break;
            }
            }

            return(ret);
        }
Ejemplo n.º 14
0
        private Boolean UpdateMessage(TSIP_Message msg)
        {
            if (!msg.ShouldUpdate)
            {
                return(true);
            }

            /* === IPSec headers (Security-Client, Security-Verify, Sec-Agree ...) === */

            /* === SigComp === */

            msg.ShouldUpdate = false; /* To avoid to update retrans. */

            return(true);
        }
        private void TSIP_Transport_NetworkEvent(object sender, TNET_Transport.TransportEventArgs e)
        {
            if (e.Type != Doubango.tinyNET.TNET_Transport.TransportEventArgs.TransportEventTypes.Data)
            {
                return;
            }

            /* === SigComp === */

            TSIP_Message message = TSIP_ParserMessage.Parse(e.Data, true);

            if (message != null && message.FirstVia != null && message.CSeq != null && message.From != null && message.To != null)
            {
                this.HandleIncomingMessage(message);
            }
            else
            {
                TSK_Debug.Error("Failed to parse message from network");
            }
        }
Ejemplo n.º 16
0
        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);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Trying -> (1xx) -> Proceeding
        /// </summary>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private Boolean Trying_2_Proceedding_X_1xx(params Object[] parameters)
        {
            TSIP_Message message = parameters[1] as TSIP_Message;

            /*	RFC 3261 - 17.1.2.2
             *      If a provisional response is received while in the "Trying" state, the
             *      response MUST be passed to the TU, and then the client transaction
             *      SHOULD move to the "Proceeding" state.
             */

            /* Cancel timers */
            if (!base.Reliable)
            {
                this.TimerE.Stop();
            }
            this.TimerF.Stop(); /* Now it's up to the UAS to update the FSM. */

            /* Pass the provisional response to the dialog. */
            return(base.Dialog.RaiseCallback(TSIP_Dialog.tsip_dialog_event_type_t.I_MSG, message));
        }
Ejemplo n.º 18
0
    private static void EoH(ref TSK_RagelState state, ref TSIP_Message message, Boolean extractContent)
    {
        int cs  = state.CS;
        int p   = state.P;
        int pe  = state.PE;
        int eof = state.EOF;

        if (extractContent && message != null)
        {
            int clen = (int)(message.ContentLength != null ? message.ContentLength.Length : 0);
            if ((p + clen) < pe && message.Content == null)
            {
                byte[] content = new byte[clen];
                Buffer.BlockCopy(state.Data, p + 1, content, 0, clen);
                message.AddContent(null, content);
                p = (p + clen);
            }
            else
            {
                p = (pe - 1);
            }
        }
    }
        private TSIP_Transport FindTransport(TSIP_Message msg, out String destIP, out ushort destPort)
        {
            TSIP_Transport transport = null;

            destIP = mStack.ProxyHost;
            destPort = mStack.ProxyPort;

            /* =========== Sending Request ========= */
            if (msg.IsRequest)
            {
                /* Request are always sent to the Proxy-CSCF */
                foreach (TSIP_Transport t in mTransports)
                {
                    if (t.Type == mStack.ProxyType)
                    {
                        transport = t;
                        break;
                    }
                }
            }

            /* =========== Sending Response ========= */
            else if (msg.FirstVia != null)
            {
                if (!String.Equals(msg.FirstVia.Transport, "UDP", StringComparison.InvariantCultureIgnoreCase)) // Reliable
                {
                    /*	RFC 3261 - 18.2.2 Sending Responses
                        If the "sent-protocol" is a reliable transport protocol such as
                        TCP or SCTP, or TLS over those, the response MUST be sent using
                        the existing connection to the source of the original request
                        that created the transaction, if that connection is still open.
                        This requires the server transport to maintain an association
                        between server transactions and transport connections.  If that
                        connection is no longer open, the server SHOULD open a
                        connection to the IP address in the "received" parameter, if
                        present, using the port in the "sent-by" value, or the default
                        port for that transport, if no port is specified.  If that
                        connection attempt fails, the server SHOULD use the procedures
                        in [4] for servers in order to determine the IP address and
                        port to open the connection and send the response to.
                    */
                }
                else
                {
                    if (!String.IsNullOrEmpty(msg.FirstVia.Maddr))/*== UNRELIABLE MULTICAST ===*/
                    {
                        /*	RFC 3261 - 18.2.2 Sending Responses
                            Otherwise, if the Via header field value contains a "maddr" parameter, the
                            response MUST be forwarded to the address listed there, using
                            the port indicated in "sent-by", or port 5060 if none is present.
                            If the address is a multicast address, the response SHOULD be
                            sent using the TTL indicated in the "ttl" parameter, or with a
                            TTL of 1 if that parameter is not present.
                        */
                    }
                    else /*=== UNRELIABLE UNICAST ===*/
                    {
                        if (!String.IsNullOrEmpty(msg.FirstVia.Received))
                        {
                            if (msg.FirstVia.RPort > 0)
                            {
                                /*	RFC 3581 - 4.  Server Behavior
                                    When a server attempts to send a response, it examines the topmost
                                    Via header field value of that response.  If the "sent-protocol"
                                    component indicates an unreliable unicast transport protocol, such as
                                    UDP, and there is no "maddr" parameter, but there is both a
                                    "received" parameter and an "rport" parameter, the response MUST be
                                    sent to the IP address listed in the "received" parameter, and the
                                    port in the "rport" parameter.  The response MUST be sent from the
                                    same address and port that the corresponding request was received on.
                                    This effectively adds a new processing step between bullets two and
                                    three in Section 18.2.2 of SIP [1].
                                */
                                destIP = msg.FirstVia.Received;
                                destPort = (ushort)msg.FirstVia.RPort;
                            }
                            else
                            {
                                /*	RFC 3261 - 18.2.2 Sending Responses
                                    Otherwise (for unreliable unicast transports), if the top Via
                                    has a "received" parameter, the response MUST be sent to the
                                    address in the "received" parameter, using the port indicated
                                    in the "sent-by" value, or using port 5060 if none is specified
                                    explicitly.  If this fails, for example, elicits an ICMP "port
                                    unreachable" response, the procedures of Section 5 of [4]
                                    SHOULD be used to determine where to send the response.
                                */
                                destIP = msg.FirstVia.Received;
                                destPort = (ushort)(msg.FirstVia.Port > 0 ? msg.FirstVia.Port : 5060);
                            }
                        }
                        else if (String.IsNullOrEmpty(msg.FirstVia.Received))
                        {
                            /*	RFC 3261 - 18.2.2 Sending Responses
                                Otherwise, if it is not receiver-tagged, the response MUST be
                                sent to the address indicated by the "sent-by" value, using the
                                procedures in Section 5 of [4].
                            */
                            destIP = msg.FirstVia.Host;
                            if (msg.FirstVia.Port > 0)
                            {
                                destPort = (ushort)msg.FirstVia.Port;
                            }
                        }
                    }
                }
            }

            //tsk_list_item_t *item;
            //tsip_transport_t *curr;
            //tsk_list_foreach(item, self->transports)
            //{
            //    curr = item->data;
            //    if(tsip_transport_have_socket(curr, msg->local_fd))
            //    {
            //        transport = curr;
            //        break;
            //    }
            //}

            return transport;
        }
Ejemplo n.º 20
0
        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;
        }
Ejemplo n.º 21
0
 internal Boolean ExecuteAction(Int32 fsmActionId, TSIP_Message message)
 {
     return(this.StateMachine.ExecuteAction(fsmActionId, this, message, this, message));
 }
Ejemplo n.º 22
0
        /// <summary>
        /// Callback function called to alert the dialog for new events from the transaction/transport layers
        /// </summary>
        /// <param name="type"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private Boolean OnCallbackEvent(tsip_dialog_event_type_t type, TSIP_Message message)
        {
            Boolean ret = false;

            switch (type)
            {
            case tsip_dialog_event_type_t.I_MSG:
            {
                if (message != null)
                {
                    if (message.IsResponse)
                    {
                        TSIP_Response response = message as TSIP_Response;
                        //
                        //	RESPONSE
                        //
                        if (response.Is1xx)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction._1xx, message, null);
                        }
                        else if (response.Is2xx)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction._2xx, message, null);
                        }
                        else if (response.StatusCode == 401 || response.StatusCode == 407 || response.StatusCode == 421 || response.StatusCode == 494)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction._401_407_421_494, message, null);
                        }
                        else if (response.StatusCode == 423)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction._423, message, null);
                        }
                        else
                        {
                            // Alert User
                            ret = base.ExecuteAction((Int32)FSMAction.Error, message, null);
                            /* TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); */
                        }
                    }
                    else
                    {
                        //
                        //	REQUEST
                        //
                        if (message.IsREGISTER)
                        {
                            ret = base.ExecuteAction((Int32)FSMAction.iREGISTER, message, null);
                        }
                    }
                }
                break;
            }

            case tsip_dialog_event_type_t.CANCELED:
            {
                ret = base.ExecuteAction((Int32)FSMAction.Cancel, message, null);
                break;
            }

            case tsip_dialog_event_type_t.TERMINATED:
            case tsip_dialog_event_type_t.TIMEDOUT:
            case tsip_dialog_event_type_t.ERROR:
            case tsip_dialog_event_type_t.TRANSPORT_ERROR:
            {
                ret = base.ExecuteAction((Int32)FSMAction.TransportError, message, null);
                break;
            }
            }

            return(true);
        }
Ejemplo n.º 23
0
 internal TSIP_EventDialog(tsip_dialog_event_type_t eventType, TSip_Session sipSession, String phrase, TSIP_Message sipMessage)
     : base(sipSession, 0, phrase, sipMessage, tsip_event_type_t.DIALOG)
 {
     mEventType = eventType;
 }
Ejemplo n.º 24
0
        // this function is only called if no transaction match
        // for responses, the transaction will always match
        internal Boolean HandleIncomingMessage(TSIP_Message message)
        {
            TSIP_Dialog  dialog  = null;
            TSIP_Transac transac = null;
            Boolean      cid_matched;
            Boolean      ret = false;

            dialog = this.FindDialog(message.CallId.Value,
                                     message.IsResponse ? message.To.Tag : message.From.Tag,
                                     message.IsResponse ? message.From.Tag : message.To.Tag,
                                     message.IsRequest ? (message as TSIP_Request).RequestType : TSIP_Message.tsip_request_type_t.NONE,
                                     out cid_matched);

            if (dialog != null)
            {
                if (message.IsCANCEL || message.IsACK)
                {
                    ret = dialog.RaiseCallback(TSIP_Dialog.tsip_dialog_event_type_t.I_MSG, message);
                    goto bail;
                }
                else
                {
                    transac = mStack.LayerTransac.CreateTransac(false, message, dialog);
                }
            }
            else
            {
                if (message.IsRequest)
                {
                    TSIP_Dialog newdialog = null;

                    switch ((message as TSIP_Request).RequestType)
                    {
                    case TSIP_Message.tsip_request_type_t.REGISTER:
                    {
                        /* incoming REGISTER */
                        TSIP_SessionRegister session = new TSIP_SessionRegister(mStack, message);
                        newdialog = new TSIP_DialogRegister(session, message.CallId == null ? null : message.CallId.Value);
                        break;
                    }
                    }

                    // for new dialog, create a new transac and start it later
                    if (newdialog != null)
                    {
                        transac = mStack.LayerTransac.CreateTransac(false, message, newdialog);
                        this.AddDialog(newdialog);
                    }
                }
            }

            if (transac != null)
            {
                ret = transac.Start((message as TSIP_Request));
            }
            else if (message.IsRequest) /* No transaction match for the SIP request */
            {
                TSIP_Response response = null;

                if (cid_matched) /* We are receiving our own message. */
                {
                    response = new TSIP_Response(482, "Loop Detected (Check your iFCs)", (message as TSIP_Request));
                    if (String.IsNullOrEmpty(response.To.Tag))/* Early dialog? */
                    {
                        response.To.Tag = "doubango";
                    }
                }
                else
                {
                    switch ((message as TSIP_Request).RequestType)
                    {
                    case TSIP_Message.tsip_request_type_t.OPTIONS:     // Hacked to work on Tiscali IMS networks
                    case TSIP_Message.tsip_request_type_t.INFO:
                    {
                        response = new TSIP_Response(405, "Method Not Allowed", (message as TSIP_Request));
                        break;
                    }

                    default:
                    {
                        response = new TSIP_Response(481, "Dialog/Transaction Does Not Exist", (message as TSIP_Request));
                        break;
                    }
                    }
                }

                if (response != null)
                {
                    // send the response
                    ret = mStack.LayerTransport.SendMessage(response.FirstVia != null ? response.FirstVia.Branch : "no-branch", response);
                }
            }

bail:
            return(ret);
        }
Ejemplo n.º 25
0
        // this function is only called if no transaction match
        // for responses, the transaction will always match
        internal Boolean HandleIncomingMessage(TSIP_Message message)
        {
            TSIP_Dialog dialog = null;
            TSIP_Transac transac = null;
            Boolean cid_matched;
            Boolean ret = false;

            dialog = this.FindDialog(message.CallId.Value,
                message.IsResponse ? message.To.Tag : message.From.Tag,
                message.IsResponse ? message.From.Tag : message.To.Tag,
                message.IsRequest ? (message as TSIP_Request).RequestType : TSIP_Message.tsip_request_type_t.NONE,
                out cid_matched);

            if (dialog != null)
            {
                if (message.IsCANCEL || message.IsACK)
                {
                    ret = dialog.RaiseCallback(TSIP_Dialog.tsip_dialog_event_type_t.I_MSG, message);
                    goto bail;
                }
                else
                {
                    transac = mStack.LayerTransac.CreateTransac(false, message, dialog);
                }
            }
            else
            {
                if (message.IsRequest)
                {
                    TSIP_Dialog newdialog = null;

                    switch ((message as TSIP_Request).RequestType)
                    {
                        case TSIP_Message.tsip_request_type_t.REGISTER:
                            {
                                /* incoming REGISTER */
                                TSIP_SessionRegister session = new TSIP_SessionRegister(mStack, message);
                                newdialog = new TSIP_DialogRegister(session, message.CallId == null ? null : message.CallId.Value);
                                break;
                            }
                    }

                    // for new dialog, create a new transac and start it later
                    if (newdialog != null)
                    {
                        transac = mStack.LayerTransac.CreateTransac(false, message, newdialog);
                        this.AddDialog(newdialog);
                    }
                }
            }

            if (transac != null)
            {
                ret = transac.Start((message as TSIP_Request));
            }
            else if (message.IsRequest) /* No transaction match for the SIP request */
            {
                TSIP_Response response = null;

                if (cid_matched) /* We are receiving our own message. */
                {
                    response = new TSIP_Response(482, "Loop Detected (Check your iFCs)", (message as TSIP_Request));
                    if (String.IsNullOrEmpty(response.To.Tag))/* Early dialog? */
                    {
                        response.To.Tag = "doubango";
                    }
                }
                else
                {
                    switch ((message as TSIP_Request).RequestType)
                    {
                        case TSIP_Message.tsip_request_type_t.OPTIONS: // Hacked to work on Tiscali IMS networks
                        case TSIP_Message.tsip_request_type_t.INFO:
                            {
                                response = new TSIP_Response(405, "Method Not Allowed", (message as TSIP_Request));
                                break;
                            }
                        default:
                            {
                                response = new TSIP_Response(481, "Dialog/Transaction Does Not Exist", (message as TSIP_Request));
                                break;
                            }
                    }
                }

                if (response != null)
                {
                    // send the response
                    ret = mStack.LayerTransport.SendMessage(response.FirstVia != null ? response.FirstVia.Branch : "no-branch", response);
                }
            }

            bail:
            return ret;
        }
Ejemplo n.º 26
0
 protected void Signal(TSIP_EventDialog.tsip_dialog_event_type_t eventType, String phrase, TSIP_Message sipMessage)
 {
     TSIP_EventDialog.Signal(eventType, mSipSession, phrase, sipMessage);
 }
Ejemplo n.º 27
0
 protected void SetLastError(short code, String phrase, TSIP_Message message)
 {
     mLastErrorCode    = code;
     mLastErrorPhrase  = phrase;
     mLastErrorMessage = message;
 }
Ejemplo n.º 28
0
        /// <summary>
        /// add Via header using the transport config
        /// </summary>
        /// <param name="branch"></param>
        /// <param name="msg"></param>
        private Boolean AddViaToMessage(String branch, TSIP_Message msg)
        {
            String ip;
            ushort port;

            if (!this.GetLocalIpAndPort(out ip, out port))
            {
                return(false);
            }

#if WINDOWS_PHONE
            if (port == 0 && (mStack.AoRPort != 0 && !String.IsNullOrEmpty(mStack.AoRIP)))
            {
                port = mStack.AoRPort;
                ip   = mStack.AoRIP;
            }
#endif

            /* is there a Via header? */
            if (msg.FirstVia == null)
            {
                /*	RFC 3261 - 18.1.1 Sending Requests
                 *              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.  This field is used for sending responses under certain
                 *              conditions, described below.  If the port is absent, the default
                 *              value depends on the transport.  It is 5060 for UDP, TCP and SCTP,
                 *              5061 for TLS.
                 */
                msg.FirstVia = new TSIP_HeaderVia(TSIP_HeaderVia.PROTO_NAME_DEFAULT, TSIP_HeaderVia.PROTO_VERSION_DEFAULT,
                                                  this.ViaProtocol, ip, (UInt16)port);
                msg.FirstVia.Params.Add(new TSK_Param("rport"));
            }

            /* updates the branch */
            if (!String.IsNullOrEmpty(branch))
            {
                msg.FirstVia.Branch = branch;
            }
            else
            {
                msg.FirstVia.Branch = String.Format("{0}_{1}", TSIP_Transac.MAGIC_COOKIE, TSK_String.Random());
            }

            /* multicast case */
            if (false)
            {
                /*	RFC 3261 - 18.1.1 Sending Requests (FIXME)
                 *              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.  Usage of IPv6 multicast is not defined
                 *              in this specification, and will be a subject of future
                 *              standardization when the need arises.
                 */
            }

            /*
             * comp=sigcomp; sigcomp-id=
             */

            return(true);
        }
Ejemplo n.º 29
0
        public Boolean Send(String branch, TSIP_Message msg, String destIP, ushort destPort)
        {
            /* Add Via and update AOR, IPSec headers, SigComp ...
             * ACK sent from the transaction layer will contains a Via header and should not be updated
             * CANCEL will have the same Via and Contact headers as the request it cancel */
            if (msg.IsRequest && (!msg.IsACK || (msg.IsACK && msg.FirstVia == null)) && !msg.IsCANCEL)
            {
                this.AddViaToMessage(branch, msg); /* should be done before tsip_transport_msg_update() which could use the Via header */
                this.AddAoRToMessage(msg);         /* AoR */
                this.UpdateMessage(msg);           /* IPSec, SigComp, ... */
            }
            else if (msg.IsResponse)
            {
                /* AoR for responses which have a contact header (e.g. 183/200 INVITE) */
                if (msg.Contact != null)
                {
                    this.AddAoRToMessage(msg);
                }

                /*	RFC 3581 - 4.  Server Behavior
                 *                  When a server compliant to this specification (which can be a proxy
                 *                  or UAS) receives a request, it examines the topmost Via header field
                 *                  value.  If this Via header field value contains an "rport" parameter
                 *                  with no value, it MUST set the value of the parameter to the source
                 *                  port of the request.
                 */
                if (msg.FirstVia.RPort == 0)
                {
                    msg.FirstVia.RPort = msg.FirstVia.Port;
                }
            }

            // serialize the message
            byte [] bytes = msg.ToBytes();

            if (bytes.Length > 1300)
            {
                /*	RFC 3261 - 18.1.1 Sending Requests (FIXME)
                 *                      If a request is within 200 bytes of the path MTU, or if it is larger
                 *                      than 1300 bytes and the path MTU is unknown, the request MUST be sent
                 *                      using an RFC 2914 [43] congestion controlled transport protocol, such
                 *                      as TCP. If this causes a change in the transport protocol from the
                 *                      one indicated in the top Via, the value in the top Via MUST be
                 *                      changed.  This prevents fragmentation of messages over UDP and
                 *                      provides congestion control for larger messages.  However,
                 *                      implementations MUST be able to handle messages up to the maximum
                 *                      datagram packet size.  For UDP, this size is 65,535 bytes, including
                 *                      IP and UDP headers.
                 */
            }

            /* === SigComp === */

            /* === Send the message === */
            //if (/*TNET_Socket.IsIPSec()*/false)
            //{
            //    return false;
            //}
            //else
            //{
            return(this.SendBytes(TNET_Socket.CreateEndPoint(destIP, destPort), bytes));
            //}
        }
        private Boolean HandleIncomingMessage(TSIP_Message message)
        {
            Boolean ret = false;

            if (message != null)
            {
                if (!(ret = mStack.LayerTransac.HandleIncomingMsg(message)))
                {
                    /* NO MATCHING TRANSACTION FOUND ==> LOOK INTO DIALOG LAYER */
                    ret = mStack.LayerDialog.HandleIncomingMessage(message);
                }
            }
            return ret;
        }
 // internal construction used to create server-side session
 internal TSIP_SessionRegister(TSIP_Stack stack, TSIP_Message message)
     : base(stack, message)
 {
 }
Ejemplo n.º 32
0
 internal static Boolean Signal(tsip_register_event_type_t eventType, TSip_Session sipSession, ushort code, String phrase, TSIP_Message sipMessage)
 {
     TSIP_EventRegister @event = new TSIP_EventRegister(eventType, sipSession, code, phrase, sipMessage);
     return @event.Signal();
 }
Ejemplo n.º 33
0
        private TSIP_Dialog FindDialog(String callid, String to_tag, String from_tag, TSIP_Message.tsip_request_type_t type, out Boolean cid_matched)
        {
            TSIP_Dialog dialog = null;
            cid_matched = false;

            mMutex.WaitOne();

            foreach (TSIP_Dialog d in mDialogs.Values)
            {
                if (String.Equals(d.CallId, callid))
                {
                    Boolean is_cancel = (type == TSIP_Message.tsip_request_type_t.CANCEL); // Incoming CANCEL
                    Boolean is_register = (type == TSIP_Message.tsip_request_type_t.REGISTER); // Incoming REGISTER
                    Boolean is_notify = (type == TSIP_Message.tsip_request_type_t.NOTIFY); // Incoming NOTIFY
                    cid_matched = true;

                    /* CANCEL Request will have the same local tag than the INVITE request -> do not compare tags */
                    if ((is_cancel || String.Equals(d.TagLocal, from_tag)) && String.Equals(d.TagRemote, to_tag))
                    {
                        dialog = d;
                        break;
                    }

                    /* REGISTER is dialogless which means that each reREGISTER or unREGISTER will have empty to tag  */
                    if (is_register /* Do not check tags */)
                    {
                        dialog = d;
                        break;
                    }

                    /*	NOTIFY could arrive before the 200 SUBSCRIBE => This is why we don't try to match both tags

                        RFC 3265 - 3.1.4.4. Confirmation of Subscription Creation
                        Due to the potential for both out-of-order messages and forking, the
                        subscriber MUST be prepared to receive NOTIFY messages before the
                        SUBSCRIBE transaction has completed.
                     */
                    if (is_notify /* Do not check tags */)
                    {
                        dialog = d;
                        break;
                    }
                }
            }

            mMutex.ReleaseMutex();

            return dialog;
        }
Ejemplo n.º 34
0
 internal TSIP_EventRegister(tsip_register_event_type_t eventType, TSip_Session sipSession, ushort code, String phrase, TSIP_Message sipMessage)
     : base(sipSession, code, phrase, sipMessage, tsip_event_type_t.REGISTER)
 {
     mEventType = eventType;
 }
Ejemplo n.º 35
0
 internal TSIP_EventDialog(tsip_dialog_event_type_t eventType, TSip_Session sipSession, String phrase, TSIP_Message sipMessage)
     : base(sipSession, 0, phrase, sipMessage, tsip_event_type_t.DIALOG)
 {
     mEventType = eventType;
 }
Ejemplo n.º 36
0
        internal static Boolean Signal(tsip_dialog_event_type_t eventType, TSip_Session sipSession, String phrase, TSIP_Message sipMessage)
        {
            TSIP_EventDialog @event = new TSIP_EventDialog(eventType, sipSession, phrase, sipMessage);

            return(@event.Signal());
        }
Ejemplo n.º 37
0
 internal static Boolean Signal(tsip_dialog_event_type_t eventType, TSip_Session sipSession, String phrase, TSIP_Message sipMessage)
 {
     TSIP_EventDialog @event = new TSIP_EventDialog(eventType, sipSession, phrase, sipMessage);
     return @event.Signal();
 }
        /// <summary>
        /// Callback function called to alert the dialog for new events from the transaction/transport layers
        /// </summary>
        /// <param name="type"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private Boolean OnCallbackEvent(tsip_dialog_event_type_t type, TSIP_Message message)
        {
            Boolean ret = false;

            switch (type)
            {
                case tsip_dialog_event_type_t.I_MSG:
                    {
                        if (message != null)
                        {
                            if (message.IsResponse)
                            {
                                TSIP_Response response = message as TSIP_Response;
                                //
                                //	RESPONSE
                                //
                                if (response.Is1xx)
                                {
                                    ret = base.ExecuteAction((Int32)FSMAction._1xx, message, null);
                                }
                                else if (response.Is2xx)
                                {
                                    ret = base.ExecuteAction((Int32)FSMAction._2xx, message, null);
                                }
                                else if (response.StatusCode == 401 || response.StatusCode == 407 || response.StatusCode == 421 || response.StatusCode == 494)
                                {
                                    ret = base.ExecuteAction((Int32)FSMAction._401_407_421_494, message, null);
                                }
                                else if (response.StatusCode == 423)
                                {
                                    ret = base.ExecuteAction((Int32)FSMAction._423, message, null);
                                }
                                else
                                {
                                    // Alert User
                                    ret = base.ExecuteAction((Int32)FSMAction.Error, message, null);
                                    /* TSK_DEBUG_WARN("Not supported status code: %d", TSIP_RESPONSE_CODE(msg)); */
                                }
                            }
                            else
                            {
                                //
                                //	REQUEST
                                //
                                if (message.IsREGISTER)
                                {
                                    ret = base.ExecuteAction((Int32)FSMAction.iREGISTER, message, null);
                                }
                            }
                        }
                        break;
                    }

                case tsip_dialog_event_type_t.CANCELED:
                    {
                        ret = base.ExecuteAction((Int32)FSMAction.Cancel, message, null);
                        break;
                    }

                case tsip_dialog_event_type_t.TERMINATED:
                case tsip_dialog_event_type_t.TIMEDOUT:
                case tsip_dialog_event_type_t.ERROR:
                case tsip_dialog_event_type_t.TRANSPORT_ERROR:
                    {
                        ret = base.ExecuteAction((Int32)FSMAction.TransportError, message, null);
                        break;
                    }
            }

            return true;
        }
 // internal construction used to create server-side session
 internal TSIP_SessionRegister(TSIP_Stack stack, TSIP_Message message)
     : base(stack, message)
 {
 }
Ejemplo n.º 40
0
 internal Boolean Send(String branch, TSIP_Message message)
 {
     return(mDialog.Stack.LayerTransport.SendMessage(branch, message));
 }
        private TSIP_Transport FindTransport(TSIP_Message msg, out String destIP, out ushort destPort)
        {
            TSIP_Transport transport = null;

            destIP   = mStack.ProxyHost;
            destPort = mStack.ProxyPort;

            /* =========== Sending Request ========= */
            if (msg.IsRequest)
            {
                /* Request are always sent to the Proxy-CSCF */
                foreach (TSIP_Transport t in mTransports)
                {
                    if (t.Type == mStack.ProxyType)
                    {
                        transport = t;
                        break;
                    }
                }
            }

            /* =========== Sending Response ========= */
            else if (msg.FirstVia != null)
            {
                if (!String.Equals(msg.FirstVia.Transport, "UDP", StringComparison.InvariantCultureIgnoreCase)) // Reliable
                {
                    /*	RFC 3261 - 18.2.2 Sending Responses
                     *                  If the "sent-protocol" is a reliable transport protocol such as
                     *                  TCP or SCTP, or TLS over those, the response MUST be sent using
                     *                  the existing connection to the source of the original request
                     *                  that created the transaction, if that connection is still open.
                     *                  This requires the server transport to maintain an association
                     *                  between server transactions and transport connections.  If that
                     *                  connection is no longer open, the server SHOULD open a
                     *                  connection to the IP address in the "received" parameter, if
                     *                  present, using the port in the "sent-by" value, or the default
                     *                  port for that transport, if no port is specified.  If that
                     *                  connection attempt fails, the server SHOULD use the procedures
                     *                  in [4] for servers in order to determine the IP address and
                     *                  port to open the connection and send the response to.
                     */
                }
                else
                {
                    if (!String.IsNullOrEmpty(msg.FirstVia.Maddr))/*== UNRELIABLE MULTICAST ===*/
                    {
                        /*	RFC 3261 - 18.2.2 Sending Responses
                         *                      Otherwise, if the Via header field value contains a "maddr" parameter, the
                         *                      response MUST be forwarded to the address listed there, using
                         *                      the port indicated in "sent-by", or port 5060 if none is present.
                         *                      If the address is a multicast address, the response SHOULD be
                         *                      sent using the TTL indicated in the "ttl" parameter, or with a
                         *                      TTL of 1 if that parameter is not present.
                         */
                    }
                    else /*=== UNRELIABLE UNICAST ===*/
                    {
                        if (!String.IsNullOrEmpty(msg.FirstVia.Received))
                        {
                            if (msg.FirstVia.RPort > 0)
                            {
                                /*	RFC 3581 - 4.  Server Behavior
                                 *                              When a server attempts to send a response, it examines the topmost
                                 *                              Via header field value of that response.  If the "sent-protocol"
                                 *                              component indicates an unreliable unicast transport protocol, such as
                                 *                              UDP, and there is no "maddr" parameter, but there is both a
                                 *                              "received" parameter and an "rport" parameter, the response MUST be
                                 *                              sent to the IP address listed in the "received" parameter, and the
                                 *                              port in the "rport" parameter.  The response MUST be sent from the
                                 *                              same address and port that the corresponding request was received on.
                                 *                              This effectively adds a new processing step between bullets two and
                                 *                              three in Section 18.2.2 of SIP [1].
                                 */
                                destIP   = msg.FirstVia.Received;
                                destPort = (ushort)msg.FirstVia.RPort;
                            }
                            else
                            {
                                /*	RFC 3261 - 18.2.2 Sending Responses
                                 *                              Otherwise (for unreliable unicast transports), if the top Via
                                 *                              has a "received" parameter, the response MUST be sent to the
                                 *                              address in the "received" parameter, using the port indicated
                                 *                              in the "sent-by" value, or using port 5060 if none is specified
                                 *                              explicitly.  If this fails, for example, elicits an ICMP "port
                                 *                              unreachable" response, the procedures of Section 5 of [4]
                                 *                              SHOULD be used to determine where to send the response.
                                 */
                                destIP   = msg.FirstVia.Received;
                                destPort = (ushort)(msg.FirstVia.Port > 0 ? msg.FirstVia.Port : 5060);
                            }
                        }
                        else if (String.IsNullOrEmpty(msg.FirstVia.Received))
                        {
                            /*	RFC 3261 - 18.2.2 Sending Responses
                             *                          Otherwise, if it is not receiver-tagged, the response MUST be
                             *                          sent to the address indicated by the "sent-by" value, using the
                             *                          procedures in Section 5 of [4].
                             */
                            destIP = msg.FirstVia.Host;
                            if (msg.FirstVia.Port > 0)
                            {
                                destPort = (ushort)msg.FirstVia.Port;
                            }
                        }
                    }
                }
            }

            //tsk_list_item_t *item;
            //tsip_transport_t *curr;
            //tsk_list_foreach(item, self->transports)
            //{
            //    curr = item->data;
            //    if(tsip_transport_have_socket(curr, msg->local_fd))
            //    {
            //        transport = curr;
            //        break;
            //    }
            //}


            return(transport);
        }
Ejemplo n.º 42
0
        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;
        }
Ejemplo n.º 43
0
        private Boolean OnCallbackEvent(tsip_transac_event_type_t type, TSIP_Message message)
        {
            Boolean ret = true;

            switch (type)
            {
                case tsip_transac_event_type_t.IncomingMessage:
                    {
                        if (message != null && message.IsResponse)
                        {
                            if ((message as TSIP_Response).Is1xx)
                            {
                                ret = base.ExecuteAction((Int32)FSMAction._1xx, message);
                            }
                            else if ((message as TSIP_Response).Is23456)
                            {
                                ret = base.ExecuteAction((Int32)FSMAction._200_to_699, message);
                            }
                            else
                            {
                                TSK_Debug.Error("Not supported status code: {0}", (message as TSIP_Response).StatusCode);
                            }
                        }
                        break;
                    }

                case tsip_transac_event_type_t.Canceled:
                case tsip_transac_event_type_t.Terminated:
                case tsip_transac_event_type_t.TimedOut:
                default:
                    {
                        break;
                    }

                case tsip_transac_event_type_t.Error:
                    {
                        ret = base.ExecuteAction((Int32)FSMAction.Error, message);
                        break;
                    }

                case tsip_transac_event_type_t.TransportError:
                    {
                        ret = base.ExecuteAction((Int32)FSMAction.TransportError, message);
                        break;
                    }
            }

            return ret;
        }
Ejemplo n.º 44
0
        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 Boolean SendMessage(String branch, TSIP_Message message)
        {
            String destIP = null;
            ushort destPort = 5060;

            TSIP_Transport transport = this.FindTransport(message, out destIP, out destPort);
            if (transport != null)
            {
                return transport.Send(branch, message, destIP, destPort);
            }

            return false;
        }