package cm.sip.hns;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.sax.StartElementListener;
import android.util.Log;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.TimerTask;

import kr.co.icontrols.ilp300_700.call.CallManager;
import kr.co.icontrols.ilp300_700.call.MyTCPServer;
import milsip.stack.sip.BSSVideo;
import milsip.stack.sip.CMCore;
import milsip.stack.sip.SIPCONTACTHeader;
import milsip.stack.sip.SIPCall;
import milsip.stack.sip.SIPHeader;
import milsip.stack.sip.SIPRequestLine;
import milsip.stack.sip.SIPStack;
import kr.co.icontrols.V40IFCCD.V40IFCCD;
import kr.co.icontrols.ilp300_700.MainActivity;
import kr.co.icontrols.ilp300_700.global.Declare;
import kr.co.icontrols.ilp300_700.global.Global;

public class SIPStun extends Service {

    static final String TAG = "SIPStun";

    public static boolean bBlackCall = false;
    public static boolean bBlackCallSupport = true;
    public static boolean bBlackCallBackgroundMode = true;
    protected static String padNumber = "";
    protected static int officeNumber = 0;   // 1:정문 2:후문 3:관할 4:관리사무소
    private static boolean isRunning = false;
    final Messenger mMessenger = new Messenger(new CmPiper());
    public SIPSignalReceiver mSIPSignalReceiver = null;
    protected int latestMenu = 0;
    boolean bLOG = true;   // true, false
    boolean bLOG_DEBUG = true;   // true, false
    boolean bLOG_INFO = true;   // true, false
    boolean bLOG_WARN = true;   // true, false
    boolean bLOG_ERROR = true;   // true, false
    android.media.Ringtone oRingTone = null;
    MediaPlayer oRingbackTone = null;
    CMCore cmcore = null;
    ConnectivityManager connectivityManager = null;
    ArrayList<Messenger> mClients = new ArrayList<Messenger>();
    boolean bPrintSIPMsg = true;
    boolean bPrintSIPMsgIO = true;

    private Context mContext;
    MyTCPServer myTCPServer;
    private String clientIP;

    public static boolean isRunning() {
        return isRunning;
    }

    private void LOG(String log) {
        if (bLOG) Log.v(TAG, log);
    }

    private void LOG_DEBUG(String log) {
        if (bLOG_DEBUG) Log.d(TAG, log);
    }

    private void LOG_INFO(String log) {
        if (bLOG_INFO) Log.i(TAG, log);
    }

    private void LOG_WARN(String log) {
        if (bLOG_INFO) Log.w(TAG, log);
    }

    private void LOG_ERROR(String log) {
        if (bLOG_INFO) Log.e(TAG, log);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }

    @Override
    public void onCreate() {

        SIPStack.SIP_MESSAGE_DEBUG = true;
        Log.i(TAG, " SIPStun onCreate called newly");
        super.onCreate();

        mContext = this;

        myTCPServer = MyTCPServer.getInstance(mContext, mHandler);

        if (myTCPServer == null) {
            Log.v("yjyoon", "TCPServer is null.");
        } else {
            myTCPServer.start();
        }

        SIPStack.setLicense("주식회사아이콘트롤스 200701243005451");
        if (SIPStack.getLicensed() == false) {
            Log.i(TAG, "라이슨스가 맞지 않습니다. (주)광해소프트에 문의하시길 바랍니다.");
            System.exit(0);
        }
        SIPStack.bootTime = new Date();
        BSSVideo.bService = false;
        BSSVideo.bViewme = false;
        SIPStack.ventureCall = true;
        // 서비스폰 타입설정 ////////////////////////////////////////////////////////////
        BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED = BSSVideo.HNS_SERVICE_LOBBY;
        //세대기:HNS_SERVICE_NEIGHBOR,
        //로비폰:HNS_SERVICE_LOBBY,
        //경비실폰:HNS_SERVICE_GUARD
        BSSVideo.HNS_SERVICE_RECEIVER_SELECTED = BSSVideo.HNS_SERVICE_NONE;
        latestMenu = BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED;
        if (BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED == BSSVideo.HNS_SERVICE_GUARD) {
            officeNumber = 1;   //1:정문 2:후문 3:관할 4:관리사무소
        } else officeNumber = 0;   //not assign

        if (!SIPStack.bActive) {
            if (SIPController.BACKGROUNDTimer != null) SIPController.BACKGROUNDTimer.cancel();
            Log.i(TAG, "SIPStack.init .");
            SIPController.init();
            SIPStack.bNetworkActive = false;
        }

        SIPStack.bBackgroundRunning = false;
        SIPStack.bGeneralPhoneDetected = false;

        getStackKey();

        try {
            String host = SIPController.getSHVE140SLocalIpAddress();
            Log.i(TAG, "Host : " + host);
            InetAddress thisComputer = null;
            if (host != null && host.length() > 0) thisComputer = InetAddress.getByName(host);
            else thisComputer = InetAddress.getByName("127.0.0.1");
            byte[] address = thisComputer.getAddress();
            if (address.length == 4) {
                int unsignedByte1 = address[0] < 0 ? address[0] + 256 : address[0];
                int unsignedByte2 = address[1] < 0 ? address[1] + 256 : address[1];
                int unsignedByte3 = address[2] < 0 ? address[2] + 256 : address[2];
                int unsignedByte4 = address[3] < 0 ? address[3] + 256 : address[3];
                SIPStack.strLocalip = unsignedByte1 + "." + unsignedByte2 + "." + unsignedByte3 + "." + unsignedByte4;
                Log.i(TAG, "[onCreate] SIPStack.strLocalip [" + SIPStack.strLocalip + "]");
            } else if (SIPStack.SIP_MESSAGE_DEBUG) {
                Log.i(TAG, "no ipv4.");
            }

            if (SIPStack.SIP_MESSAGE_DEBUG) {
                Log.i(TAG, SIPStack.strLocalip + " founded.");
            }

            if (SIPStack.stackkey.strServerDomain == null) {
                SIPStack.stackkey.strServerDomain = "";
            }

            if (SIPStack.bDirectCall) {
                boolean bValidroom = getMyroomname();
                if (bValidroom == false) {
                    Log.i("SIPStun", "Invalid room");
                    dialerPadNumber("");
                } else {
                    dialerPadNumber(padNumber);
                }
            }

            if (!SIPStack.bActive) {
                SIPController.initSound();
                mSIPSignalReceiver = new SIPSignalReceiver(thisComputer, SIPStack.localPort);

                if (mSIPSignalReceiver != null) {
                    mSIPSignalReceiver.start();
                    SIPStack.localPort = SIPStack.SIP_SIGNAL_PORT;
                    SIPStack.ipdns.bSipAddressResolved = false;
                    cmcore = new CMCore();
                    connectivityManager = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);

                    initializeCm(address, SIPStack.strLocalip.getBytes(), SIPStack.localPort, SIPStack.stackkey.strServerHost, SIPStack.stackkey.serverPort, SIPStack.stackkey.strServerDomain, SIPStack.stackkey.strId.getBytes(),
                            SIPStack.stackkey.strCid.getBytes(), SIPStack.stackkey.strAuthid.getBytes(), SIPStack.stackkey.strAuthpassword.getBytes());

                    SIPController.audioRTPManager = new RTPManager(this, SIPStack.SIP_MEDIATYPE_AUDIO);
                    SIPSound.amAudioManager = (AudioManager) this.getSystemService(AUDIO_SERVICE);
                    SIPSound.initRoute();

                    if (SIPController.sipCall == null) {
                        Log.i(TAG, "sipCall is null");
                    }
                    SIPStack.bActive = true;
                }
            }

            registerSIPStunBR();
            startAppLiveSignalChecker();

        } catch (UnknownHostException uhe) {
            Log.e(TAG, "[UnknownHostException] onCreate()");
            uhe.printStackTrace();
        } catch (Exception e) {
            Log.e(TAG, "[Exception] onCreate()");
            e.printStackTrace();
        }
        Log.i(TAG, "Service Started.");
        CMCore.bPausing = false;
        isRunning = true;
    }

    public boolean getMyroomname() {
        try {
            padNumber = "";
            String host = SIPController.getSHVE140SLocalIpAddress();
            InetAddress thisComputer = null;

            if (host != null && host.length() > 0) thisComputer = InetAddress.getByName(host);
            else thisComputer = InetAddress.getByName("127.0.0.1");

            byte[] address = thisComputer.getAddress();

            if (address.length == 4) {
                int unsignedByte1 = address[0] < 0 ? address[0] + 256 : address[0];
                int unsignedByte2 = address[1] < 0 ? address[1] + 256 : address[1];
                int unsignedByte3 = address[2] < 0 ? address[2] + 256 : address[2];
                int unsignedByte4 = address[3] < 0 ? address[3] + 256 : address[3];
                SIPStack.strLocalip = unsignedByte1 + "." + unsignedByte2 + "." + unsignedByte3 + "." + unsignedByte4;
                Log.i(TAG, "[getMyroomname] SIPStack.strLocalip [" + SIPStack.strLocalip + "]");

                String[] aDeviceName = Global.makeDeviceName(SIPStack.strLocalip);
//                for (int i = 0; i < aDeviceName.length; i++)
//                    Log.i(TAG, "[getMyroomname] aDeviceName[" + i + "] = " + aDeviceName[i]);

                if (aDeviceName[0] == Declare.DeviceString.strType_Lobby) {
                    // 로비폰
                    padNumber = aDeviceName[1] + "동 " + aDeviceName[2] + "번 로비";
                } else if (aDeviceName[0] == Declare.DeviceString.strType_Guard) {
                    // 경비실기
                    padNumber = aDeviceName[1] + "동 " + aDeviceName[2] + "번 경비실";
                } else {
                    // 세대단말기
                    padNumber = aDeviceName[1] + "동 " + aDeviceName[2] + "호";
                }

                SIPStack.stackkey.strId = MainActivity.mCallController.makeSIPID(SIPStack.strLocalip);
                SIPStack.stackkey.strAuthid = MainActivity.mCallController.makeSIPID(SIPStack.strLocalip);
                Log.i(TAG, "[getMyroomname] strId [" + SIPStack.stackkey.strId + "], strAuthid [" + SIPStack.stackkey.strAuthid + "]");
                return true;
            } else return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getMyroomname()");
            e.printStackTrace();
        }
        return false;
    }

    private void getStackKey() {
        SharedPreferences prefs = getSharedPreferences("PrefName", MODE_PRIVATE);

        String textId = prefs.getString(SIPStack.stackkey.KEY_BSS_ID, "");
        String textAuthid = prefs.getString(SIPStack.stackkey.KEY_BSS_AUTHID, "");
        String textPassword = prefs.getString(SIPStack.stackkey.KEY_BSS_PASSWORD, "");
        String textCid = prefs.getString(SIPStack.stackkey.KEY_BSS_CID, "");

        String textServerip = prefs.getString(SIPStack.stackkey.KEY_BSS_SERVERIP, "");
        String textDomain = prefs.getString(SIPStack.stackkey.KEY_BSS_SERVERDOMAIN, "");
        String textPort = prefs.getString(SIPStack.stackkey.KEY_BSS_SERVERPORT, "");
        String textImsi = prefs.getString(SIPStack.stackkey.KEY_BSS_IMSI, "");
        String textGeneralPhone = prefs.getString(SIPStack.stackkey.KEY_BSS_GENERALPHONE, "");
        String textWebid = prefs.getString(SIPStack.stackkey.KEY_BSS_WEBID, "");
        String textWebpwd = prefs.getString(SIPStack.stackkey.KEY_BSS_WEBPWD, "");
        String textLatestdial = prefs.getString(SIPStack.stackkey.KEY_BSS_LATESTDIAL, "");
        String textForward = prefs.getString(SIPStack.stackkey.KEY_BSS_FORWARD, "");

        SIPStack.stackkey.strImsi = textImsi.trim();
        SIPStack.stackkey.strGeneralPhone = textGeneralPhone.trim();
        SIPStack.stackkey.strWebId = textWebid.trim();
        SIPStack.stackkey.strWebPwd = textWebpwd.trim();
        SIPStack.userDial.latestDial = textLatestdial.trim();

        Log.i(TAG, "[getStackKey] >>>>>WEB ID : " + SIPStack.stackkey.strWebId + "   WEB PWD : " + SIPStack.stackkey.strWebPwd);

        SIPStack.stackkey.strId = textId.trim();
        SIPStack.stackkey.strCid = textCid.trim();
        SIPStack.stackkey.strAuthid = textAuthid.trim();
        SIPStack.stackkey.strAuthpassword = textPassword.trim();
        SIPStack.stackkey.strServerHost = textServerip.trim();
        SIPStack.stackkey.strServerDomain = textDomain.trim();

        if (textPort.trim().length() > 0)
            SIPStack.stackkey.serverPort = Integer.parseInt(textPort.trim());
        else SIPStack.stackkey.serverPort = 5060;

        // 192.168.10.21
        SIPStack.stackkey.strId = "07077392005";
        SIPStack.stackkey.strAuthid = "07077392005";
        SIPStack.stackkey.strAuthpassword = "002005";
        SIPStack.stackkey.strServerHost = "192.168.10.2";
        SIPStack.stackkey.serverPort = 5060;

        SIPController.forward.setValue(textForward.trim());

        if (SIPStack.SIP_MESSAGE_DEBUG) {
            Log.i(TAG, "ID : " + SIPStack.stackkey.strId);
            Log.i(TAG, "CID : " + SIPStack.stackkey.strCid);
            Log.i(TAG, "AUTHID : " + SIPStack.stackkey.strAuthid);
            Log.i(TAG, "AUTHPASSWORD : " + SIPStack.stackkey.strAuthpassword);
            Log.i(TAG, "SERVERHOST : " + SIPStack.stackkey.strServerHost);
            Log.i(TAG, "SERVERDOMAIN : " + SIPStack.stackkey.strServerDomain);
            Log.i(TAG, "SERVERPORT : " + SIPStack.stackkey.serverPort);
            Log.i(TAG, "FORWARD set : " + SIPController.forward.bForward + " type : " + SIPController.forward.iForwardTarget + " number : " + SIPController.forward.number);
        }
        return;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "Received start id " + startId + " : " + intent);
        return START_STICKY; // run until explicitly stopped.
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (SIPStack.bUseCtrlTimer) {
            if (cmcore.SIGNALCTRLTimer != null) {
                cmcore.SIGNALCTRLTimer.cancel();
            }
            cmcore.SIGNALCTRLTimer = null;
        } else {
            if (cmcore.SIGNALCTRLThread != null && cmcore.SIGNALCTRLThread.isAlive()) {
                cmcore.SIGNALCTRLThread.interrupt();
                cmcore.SIGNALCTRLRunning = false;
            }
        }
        mSIPSignalReceiver.interrupt();
        SIPStack.bActive = false;
        Log.i(TAG, "Service Stopped.");
        isRunning = false;
    }
    //SIPCm
    //SIPStack.SIPCTRL_INTERVAL

    public void initializeCm(byte[] byteAddress, byte[] byteLocalip, int localport, byte[] byteServerip, int serverport, byte[] byteServerdomain, byte[] byteId, byte[] byteCid, byte[] byteAuthid, byte[] byteAuthpassword) {
        SIPController.sipCall = new SIPCall();
        // Multicall part
        SIPController.pendingCall = new SIPCall(true);
        if (connectivityManager != null && connectivityManager.getActiveNetworkInfo() != null) {
            NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();

            switch (activeNetwork.getType()) {

                case ConnectivityManager.TYPE_WIMAX:   // 4g 망 체크
                    SIPStack.isInternetWiMax = true;
                    SIPStack.isInternetWiFi = false;
                    SIPStack.isInternetMobile = false;
                    SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                    break;

                case ConnectivityManager.TYPE_WIFI:   // wifi망 체크
                    SIPStack.isInternetWiMax = false;
                    SIPStack.isInternetWiFi = true;
                    SIPStack.isInternetMobile = false;
                    SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                    break;

                case ConnectivityManager.TYPE_MOBILE: // 3g 망 체크
                    SIPStack.isInternetWiMax = false;//false;
                    SIPStack.isInternetWiFi = false;
                    SIPStack.isInternetMobile = true;
                    SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                    break;
            }
        }

        cmcore.action_0(byteLocalip, localport, byteServerip, serverport, byteServerdomain, byteId, byteCid, byteAuthid, byteAuthpassword);

        if (SIPStack.bUseCtrlTimer) {
            cmcore.SIGNALCTRLTimer.scheduleAtFixedRate(new CTRLTimerTask(), 0, SIPStack.SIPCTRL_INTERVAL);
        } else {
            cmcore.SIGNALCTRLThread = new SIGNALCTRLThread();
            if (cmcore.SIGNALCTRLThread != null) {
                cmcore.SIGNALCTRLRunning = true;
                cmcore.SIGNALCTRLThread.start();
            }
        }

        if (connectivityManager != null && connectivityManager.getActiveNetworkInfo() != null) {

            NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();

            switch (activeNetwork.getType()) {

                case ConnectivityManager.TYPE_WIMAX: // 4g 망 체크
                    SIPStack.isInternetWiMax = true;
                    SIPStack.isInternetWiFi = false;
                    SIPStack.isInternetMobile = false;
                    SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                    break;

                case ConnectivityManager.TYPE_WIFI: // wifi망 체크
                    SIPStack.isInternetWiMax = false;
                    SIPStack.isInternetWiFi = true;
                    SIPStack.isInternetMobile = false;
                    SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                    break;

                case ConnectivityManager.TYPE_MOBILE: // 3g 망 체크
                    SIPStack.isInternetWiMax = false;
                    SIPStack.isInternetWiFi = false;
                    SIPStack.isInternetMobile = true;
                    SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                    break;
            }
        }

        cmcore.netcheckIntervalTimer = new Date();

        try {
            String host = SIPController.getSHVE140SLocalIpAddress();
            if (cmcore.action_net_2(host)) {
                sendRegister();
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] String host = SIPController.getSHVE140SLocalIpAddress()");
        }
    }   // SipSignalReceiver()

    public void initializeCm(byte[] byteAddress, byte[] byteLocalip, int localport, String strServerHost, int serverport, String strServerDomain, byte[] byteId, byte[] byteCid, byte[] byteAuthid, byte[] byteAuthpassword) {
        SIPController.sipCall = new SIPCall();
        // Multicall part
        SIPController.pendingCall = new SIPCall(true);

        cmcore.action_1(byteAddress, byteLocalip, localport, strServerHost, serverport, strServerDomain, byteId, byteCid, byteAuthid, byteAuthpassword);

        if (SIPStack.bUseCtrlTimer) {
            cmcore.SIGNALCTRLTimer.scheduleAtFixedRate(new CTRLTimerTask(), 0, SIPStack.SIPCTRL_INTERVAL);
        } else {
            cmcore.SIGNALCTRLThread = new SIGNALCTRLThread();
            if (cmcore.SIGNALCTRLThread != null) {
                cmcore.SIGNALCTRLRunning = true;
                cmcore.SIGNALCTRLThread.start();
            }
        }
    }   // SipSignalReceiver()

    public void resumeCm(byte[] byteAddress, byte[] byteLocalip, int localport, String strServerHost, int serverport, String strServerDomain, byte[] byteId, byte[] byteCid, byte[] byteAuthid, byte[] byteAuthpassword) {
        SIPStack.ipdns.bSipAddressResolved = true;
        SIPStack.ipdns.sipTry = 0;
        // SERVICE MESSAGE NEEDED
        if (SIPStack.bDirectCall == false) dialerRegistStatus(SIPStack.bNetworkActive);
    }//SipSignalReceiver()

    public void resetConfiguration(String strId, String strCid, String strAuthid, String strAuthpassword, String strServerHost, String strServerDomain, int serverport) {
        // Set server information
        cmcore.action_2(strId, strCid, strAuthid, strAuthpassword, strServerHost, strServerDomain, serverport);
        sendRegister();
    }

    public void SIPCTRLRegister() {
        if (SIPStack.ipdns.bSipAddressResolved == false) {
            return;
        }

        Date currentTime = new Date();
        int duration = (int) (currentTime.getTime() - cmcore.regTime.getTime()) / 1000;
        int startduration = (int) (currentTime.getTime() - SIPStack.bootTime.getTime()) / 1000;

        if (cmcore.regState == SIPStack.SIP_REGSTATE_IDLE && startduration > 0 && startduration < 10 && mSIPSignalReceiver != null && mSIPSignalReceiver.bReady) {
            byte[] buffer = cmcore.message.getBytes();
            if (cmcore.message.length() > 0) {

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, cmcore.message);

                cmcore.regState = SIPStack.SIP_REGSTATE_REGISTERING;
                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(cmcore.serverIp, cmcore.serverPort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
                cmcore.regTime = new Date();
            }
        } else if (decideRegister() && cmcore.regState != SIPStack.SIP_REGSTATE_REGISTERING && cmcore.regState != SIPStack.SIP_REGSTATE_AUTHORIZING && cmcore.regState != SIPStack.SIP_REGSTATE_UNAVAILABLE) {
            cmcore.regState = SIPStack.SIP_REGSTATE_REGISTERING;
            sendRegister();
        } else if (duration >= SIPStack.CS_TIMEOUT_RESPONSE && cmcore.regState == SIPStack.SIP_REGSTATE_REGISTERING) {   // 30
            cmcore.regState = SIPStack.SIP_REGSTATE_REGISTERING;
            sendRegister();
        }
        return;
    }

    public void SIPCTRLCall() {
//	    Log.e(TAG, "[SIPCTRLCall] ========== START ==========");
        Date currentTime = new Date();
        long durationMilli = Math.abs(currentTime.getTime() - cmcore.ctrlIntervalTimer.getTime());
        long durationRegistStatus = Math.abs((currentTime.getTime() - cmcore.registStatusTimer.getTime()) / 1000);
        if (durationMilli < 500) {
//	        Log.w(TAG, "[SIPCTRLCall] durationMilli = " + durationMilli);
            return;
        } else {
//	        Log.e(TAG, "[SIPCTRLCall] ========== durationMilli = " + durationMilli + "==========");
            cmcore.ctrlIntervalTimer = new Date();
            durationMilli = Math.abs((currentTime.getTime() - cmcore.netcheckIntervalTimer.getTime()) / 1000);
//			Log.w(TAG, "[SIPCTRLCall] durationMilli = " + durationMilli);
            if (durationMilli > SIPStack.NETWORKIF_CHECK_TIME) {
                if (connectivityManager != null && connectivityManager.getActiveNetworkInfo() != null) {

                    NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();

                    switch (activeNetwork.getType()) {

                        case ConnectivityManager.TYPE_WIMAX: // 4g 망 체크
                            if (SIPStack.isInternetWiMax == false && SIPStack.bBackgroundRunning)
                                SIPStack.bShutdownApplication = true;
                            SIPStack.isInternetWiMax = true;
                            SIPStack.isInternetWiFi = false;
                            SIPStack.isInternetMobile = false;
                            SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                            break;

                        case ConnectivityManager.TYPE_WIFI: // wifi망 체크
                            if (SIPStack.isInternetWiFi == false && SIPStack.bBackgroundRunning)
                                SIPStack.bShutdownApplication = true;
                            SIPStack.isInternetWiMax = false;
                            SIPStack.isInternetWiFi = true;
                            SIPStack.isInternetMobile = false;
                            SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                            break;

                        case ConnectivityManager.TYPE_MOBILE: // 3g 망 체크
                            if (SIPStack.isInternetMobile == false && SIPStack.bBackgroundRunning)
                                SIPStack.bShutdownApplication = true;
                            SIPStack.isInternetWiMax = false;
                            SIPStack.isInternetWiFi = false;
                            SIPStack.isInternetMobile = true;
                            SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                            break;
                    }
                }

                cmcore.netcheckIntervalTimer = new Date();

                try {
                    String host = SIPController.getSHVE140SLocalIpAddress();
                    if (cmcore.action_net_3(host)) {
                        sendUNRegister(cmcore.previfIp, cmcore.previfPort);
                        cmcore.regState = SIPStack.SIP_REGSTATE_UNREGISTERING;
                    }
                } catch (Exception e) {
                    Log.e(TAG, "[Exception] String host = SIPController.getSHVE140SLocalIpAddress()");
                }
            }
        }

        if (durationRegistStatus > 0) {
            if ((SIPStack.bIntraffic || SIPStack.bOuttraffic) && SIPController.sipCall != null && SIPController.sipCall.flag == false) {
                if (cmcore.regState == SIPStack.SIP_REGSTATE_REGISTERED) {
                    // SERVICE MESSAGE NEEDED
                    if (SIPStack.bDirectCall == false) dialerRegistStatus(true);
                } else {
                    // SERVICE MESSAGE NEEDED
                    if (SIPStack.bDirectCall == false) dialerRegistStatus(false);
                }
                cmcore.registStatusTimer = new Date();
            } else if (durationRegistStatus > 3) {
                if (cmcore.regState == SIPStack.SIP_REGSTATE_REGISTERED) {
                    // SERVICE MESSAGE NEEDED
                    if (SIPStack.bDirectCall == false) dialerRegistStatus(true);
                } else {
                    // SERVICE MESSAGE NEEDED
                    if (SIPStack.bDirectCall == false) dialerRegistStatus(false);
                }
                cmcore.registStatusTimer = new Date();
            }
        }

        // Multicall call state processing
        if (SIPController.pendingCall != null && SIPController.pendingCall.flag) {
            if (SIPController.pendingCall.callTime_TI != null)
                SIPController.pendingCall.expiresTI = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_TI.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T0 != null)
                SIPController.pendingCall.expiresT0 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T0.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T00 != null)
                SIPController.pendingCall.expiresT00 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T00.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T1 != null)
                SIPController.pendingCall.expiresT1 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T1.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T2 != null)
                SIPController.pendingCall.expiresT2 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T2.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T3 != null)
                SIPController.pendingCall.expiresT3 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T3.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T4 != null)
                SIPController.pendingCall.expiresT4 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T4.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T5 != null)
                SIPController.pendingCall.expiresT5 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T5.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T6 != null)
                SIPController.pendingCall.expiresT6 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T6.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T7 != null)
                SIPController.pendingCall.expiresT7 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T7.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T8 != null)
                SIPController.pendingCall.expiresT8 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T8.getTime()) / 1000;
            if (SIPController.pendingCall.callTime_T9 != null)
                SIPController.pendingCall.expiresT9 = (int) (currentTime.getTime() - SIPController.pendingCall.callTime_T9.getTime());//milli seconds

            if (SIPController.pendingCall.bAsMaster) {
                // CONNECTED TIMEOUT PROCESSING
                SIPController.sipCall.exceptionT4();
                Log.e(TAG, "[JEFF] ========== RTP END 18 ==========");
                if (SIPController.audioRTPManager != null)
                    SIPController.audioRTPManager.RTPEnd();
                if (SIPStack.bDirectCall) {
                    // SERVICE MESSAGE NEEDED
                    dialerVideoSet(false);
                }

                sendBye();
                SIPController.sipCall.resetCall();
                SIPController.sipCall = SIPController.pendingCall;
                SIPController.pendingCall = new SIPCall();

                // for temporary
                if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
                    Log.i(TAG, "call exchange : " + SIPController.sipCall.remoteIp);
                    BSSVideo.bProgressvideooffer = true;
                    sendProgressingwithbody(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort);
                    if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
                        // Phone status set
                        // SERVICE MESSAGE NEEDED
                        updateDialerStatus("Incoming call accept.", false);
                        directsendAccept();
                        return;
                    }
                }
                return;
            }

            if (SIPController.pendingCall.bRejectRequest) {
                if (SIPController.bMulticallBusyResponse) rejectPendingCall(486);
                else rejectPendingCall(480);
            } else if (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_IDLE) {
                if (SIPController.pendingCall.expiresTI > SIPStack.CS_TIMEOUT_TI) {
                    SIPController.pendingCall.resetCall();
                }
            } else if (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_DISCONNECTING) {
                if (SIPController.pendingCall.expiresT5 > SIPStack.CS_TIMEOUT_T5) {
                    // DISCONNECTING TIMEOUT PROCESSING
                    SIPController.pendingCall.resetCall();
                }
            } else if (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_TERMINATING) {
                if (SIPController.pendingCall.expiresT6 > SIPStack.CS_TIMEOUT_T6) {
                    SIPController.pendingCall.resetCall();
                }
            } else if (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
                if (SIPController.pendingCall.expiresT7 > SIPStack.CS_TIMEOUT_T7) {
                    SIPController.pendingCall.exceptionT7();
                    rejectPendingCall(408);
                }
            } else if (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_CANCELLING) {
                if (SIPController.pendingCall.expiresT8 > SIPStack.CS_TIMEOUT_T8) {
                    SIPController.pendingCall.resetCall();
                }
            } else if (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_RECANCELLING) {
                if (SIPController.pendingCall.expiresT8 > SIPStack.CS_TIMEOUT_T8) {
                    SIPController.pendingCall.resetCall();
                }
            } else if (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_CANCELREMOTEACCEPTED) {
                if (SIPController.pendingCall.expiresT8 > SIPStack.CS_TIMEOUT_T8) {
                    SIPController.pendingCall.resetCall();
                }
            } else if (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_CANCELLED) {
                if (SIPController.pendingCall.expiresT8 > SIPStack.CS_TIMEOUT_T8) {
                    SIPController.pendingCall.resetCall();
                }
            }
        }

        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) {
            if (cmcore.regState == SIPStack.SIP_REGSTATE_REGISTERED) {
                // SERVICE MESSAGE NEEDED
                updateDialerStatus("Ready.", cmcore.bRequestReadySet);
            } else {
                // SERVICE MESSAGE NEEDED
                if (SIPStack.bDirectCall == false)
                    updateDialerStatus("Not registered.", cmcore.bRequestReadySet);
            }

            if (cmcore.bRequestReadySet) {
                cmcore.bRequestReadySet = false;
            }
            return;
        }

        if (SIPController.sipCall != null && SIPController.sipCall.flag) {
            if (SIPController.sipCall.callTime_TI != null)
                SIPController.sipCall.expiresTI = (int) (currentTime.getTime() - SIPController.sipCall.callTime_TI.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T0 != null)
                SIPController.sipCall.expiresT0 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T0.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T00 != null)
                SIPController.sipCall.expiresT00 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T00.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T1 != null)
                SIPController.sipCall.expiresT1 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T1.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T2 != null)
                SIPController.sipCall.expiresT2 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T2.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T3 != null)
                SIPController.sipCall.expiresT3 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T3.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T4 != null)
                SIPController.sipCall.expiresT4 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T4.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T5 != null)
                SIPController.sipCall.expiresT5 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T5.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T6 != null)
                SIPController.sipCall.expiresT6 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T6.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T7 != null)
                SIPController.sipCall.expiresT7 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T7.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T8 != null)
                SIPController.sipCall.expiresT8 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T8.getTime()) / 1000;
            if (SIPController.sipCall.callTime_T9 != null)
                SIPController.sipCall.expiresT9 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T9.getTime());

            if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_IDLE) {
                if (SIPController.sipCall.expiresTI > SIPStack.CS_TIMEOUT_TI) {
                    // IDLE TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionTI();
                    //SERVICE MESSAGE NEEDED
                    updateDialerStatus("Ready.", true);
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_INVITING) {
                if ((SIPStack.ventureCall || SIPStack.bDirectCall) && SIPController.sipCall.expiresT00 > 3) {
                    sendReInvite();
                    SIPStack.ventureCall = false;
                    //Log.i(TAG, "+++++++ send repeat invite:");
                } else if (SIPController.sipCall.expiresT00 > SIPStack.CS_TIMEOUT_T00) {
                    //INVITING REPEAT TIMEOUT PROCESSING
                    sendReInvite();
                    SIPStack.ventureCall = false;
                }

                if (SIPController.sipCall.expiresT0 > SIPStack.CS_TIMEOUT_T000) {
                    // Homenetwork Inviting Timeout add
                    Log.i(TAG, " " + SIPController.sipCall.expiresT0);
                    sendCancel();
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROCEEDING) {
                if (SIPController.sipCall.expiresT1 > SIPStack.CS_TIMEOUT_T1) {
                    //PROCEEDING TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionT1();
                    Log.e(TAG, "[JEFF] ========== RTP END 19 ==========");
                    if (SIPController.audioRTPManager != null)
                        SIPController.audioRTPManager.RTPEnd();
                    if (SIPStack.bDirectCall) {
                        //SERVICE MESSAGE NEEDED
                        dialerVideoSet(false);
                    }
                    sendCancel();
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROGRESSING) {
                if (SIPController.sipCall.expiresT2 > SIPStack.CS_TIMEOUT_T2) {
                    //PROGRESSING TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionT2();
                    Log.e(TAG, "[JEFF] ========== RTP END 20 ==========");
                    if (SIPController.audioRTPManager != null)
                        SIPController.audioRTPManager.RTPEnd();
                    if (SIPStack.bDirectCall) {
                        //SERVICE MESSAGE NEEDED
                        dialerVideoSet(false);
                    }
                    sendCancel();
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_ACCEPTED || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_REMOTEACCEPTED) {
                if (SIPController.sipCall.expiresT3 > SIPStack.CS_TIMEOUT_T3) {
                    //ACCEPTED TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionT3();
                    Log.e(TAG, "[JEFF] ========== RTP END 21 ==========");
                    if (SIPController.audioRTPManager != null)
                        SIPController.audioRTPManager.RTPEnd();
                    if (SIPStack.bDirectCall) {
                        //SERVICE MESSAGE NEEDED
                        dialerVideoSet(false);
                    }
                    sendBye();
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CONNECTED) {
                if (SIPController.sipCall.expiresT4 > SIPStack.CS_TIMEOUT_T4) {
                    //CONNECTED TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionT4();
                    Log.e(TAG, "[JEFF] ========== RTP END 22 ==========");
                    if (SIPController.audioRTPManager != null)
                        SIPController.audioRTPManager.RTPEnd();
                    if (SIPStack.bDirectCall) {
                        //SERVICE MESSAGE NEEDED
                        dialerVideoSet(false);
                    }
                    sendBye();
                } else {
                    int expiresT40 = 0;
                    if (SIPController.sipCall.callTime_T40 != null) {
                        expiresT40 = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T40.getTime()) / 1000;
                        if (expiresT40 > 0) {
                            //int hour=SIPController.sipCall.expiresT4/3600;
                            //int min=(SIPController.sipCall.expiresT4-hour*3600)/60;
                            //int sec=SIPController.sipCall.expiresT4-hour*3600-min*60;
                            //String s=hour+":"+min+":"+sec;
                            //boolean bWakeup=false;
                            //if(sec==0 && min>0) bWakeup=true;
                            //parent.updateDuration(0,s,bWakeup);
                            SIPController.sipCall.callTime_T40 = new Date();
                        }
                    }

                    try {
                        if (SIPController.audioRTPManager != null && SIPController.sipCall.expiresT4 > 1 && SIPController.audioRTPManager.bDisableVoice == false) {
                            int muteDuration = (int) (currentTime.getTime() - SIPController.audioRTPManager.rtpCore.rtpArrivalTime.getTime());
//					        Log.e(TAG, "[JEFF] ========== RTP END 23 ========== muteDuration [" + muteDuration + "]");
//                            if (muteDuration > 3000) {
//                                // milliseconds
//                                Log.e(TAG, "[JEFF] ========== RTP END 23 ==========");
//                                if (SIPController.audioRTPManager != null)
//                                    SIPController.audioRTPManager.RTPEnd();
//                                if (SIPStack.bDirectCall) {
//                                    //SERVICE MESSAGE NEEDED
//                                    dialerVideoSet(false);
//                                }
//                                sendBye();
//                            }
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "[Exception] dialerVideoSet(false)");
                    }
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_DISCONNECTING) {
                if (SIPController.sipCall.bByedisconnected && SIPController.sipCall.expiresT9 > 500) {
                    //resend bye
                    resendBye();
                }

                if (SIPController.sipCall.expiresT5 > SIPStack.CS_TIMEOUT_T5) {
                    //DISCONNECTING TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionT5();
                    SIPController.sipCall.resetCall();
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_TERMINATING) {
                if (SIPController.sipCall.expiresT6 > SIPStack.CS_TIMEOUT_T6) {
                    dialerNotifyCallEnd("Call Terminating.", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
                    SIPController.sipCall.exceptionT6();
                    cmcore.ctrlIntervalTimer = new Date();
                    cmcore.bRequestReadySet = true;
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
                if (SIPController.sipCall.expiresT7 > SIPStack.CS_TIMEOUT_T7) {
                    //OFFERRED TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionT7();
                    Log.e(TAG, "[JEFF] ========== RTP END 24 ==========");
                    if (SIPController.audioRTPManager != null)
                        SIPController.audioRTPManager.RTPEnd();

                    if (SIPStack.bDirectCall) {
                        //SERVICE MESSAGE NEEDED
                        dialerVideoSet(false);
                    }
                    rejectCall(408);
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CANCELLING) {
                if (SIPController.sipCall.expiresT8 > SIPStack.CS_TIMEOUT_T80) {
                    //CANCELLING TIMEOUT PROCESSING
                    sendRecancel();
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_RECANCELLING) {
                if (SIPController.sipCall.expiresT8 > SIPStack.CS_TIMEOUT_T8) {
                    //CANCELLING TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionT8();
                    //SERVICE MESSAGE NEEDED

                    Log.e(TAG, "[JEFF] ========== RTP END 25 ==========");
                    if (SIPController.audioRTPManager != null)
                        SIPController.audioRTPManager.RTPEnd();
                    if (SIPStack.bDirectCall) {
                        // SERVICE MESSAGE NEEDED
                        dialerVideoSet(false);
                    }

                    dialerNotifyCallEnd("전화를 받지 않습니다.", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
                    SIPController.sipCall.resetCall();
                }
            } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CANCELREMOTEACCEPTED) {
                if (SIPController.sipCall.expiresT8 > SIPStack.CS_TIMEOUT_T8) {
                    dialerNotifyCallFail(487, SIPController.sipCall.remoteIp);
                    // CANCELLING TIMEOUT PROCESSING
                    SIPController.sipCall.exceptionT8();
                    SIPController.sipCall.resetCall();
                }
            }
        } else if (SIPController.sipCall.callMode == SIPStack.SIP_CALLMODE_HOLD) {
            // more job
        }
        return;
    }

    public int SIPParser(String strMessage, int nMSGType, int nMethodType) {
        if (strMessage == null || strMessage.length() <= 0) return 0;

        boolean bSendRegister = false;

        if (bPrintSIPMsgIO) {
            Log.i(TAG, "[SIPParser] nMSGType [" + nMSGType + "], nMethodType [" + nMethodType + "]");
            printSIPMessage(MESSAGE.RECEIVE, strMessage);
        }

        if (nMSGType != SIPStack.SIP_MSGTYPE_RESPONSE || nMethodType != SIPStack.SIP_METHODTYPE_REGISTER)
            return -1;

        SIPRequestLine requestLine = new SIPRequestLine(strMessage);

        if (requestLine == null || requestLine.flag == false) return 0;

        switch (requestLine.code) {

            case 200:
                cmcore.repeatRegisterCount = 0;
                if (cmcore.regState == SIPStack.SIP_REGSTATE_REGISTERING || cmcore.regState == SIPStack.SIP_REGSTATE_AUTHORIZING || cmcore.regState == SIPStack.SIP_REGSTATE_UNREGISTERING) {

                    SIPCONTACTHeader contactHeader = cmcore.action_reg_0(strMessage);

                    if (contactHeader != null && contactHeader.flag == false) {
                        contactHeader = new SIPCONTACTHeader(strMessage);
                    }

                    if (contactHeader == null || contactHeader.flag == false || contactHeader.expires == 0 || cmcore.regState == SIPStack.SIP_REGSTATE_UNREGISTERING) {
                        if (cmcore.bInterfaceChanged) {
                            cmcore.bInterfaceChanged = false;
                            cmcore.regState = SIPStack.SIP_REGSTATE_REGISTERING;
                            sendRegister();
                        } else {
                            cmcore.regState = SIPStack.SIP_REGSTATE_IDLE;
                        }
                        break;
                    }
                    //Log.i(TAG, ">>>>>> Valid contact Header found. : " + contactHeader.display);
                    // GET EXPIRES HEADER
                    if (contactHeader.expires > 0) {
                        cmcore.expiresSeconds = contactHeader.getExpires();
                    } else if (contactHeader.expires < 0) {
                        SIPHeader expiresHeader = new SIPHeader(strMessage, SIPStack.SIP_HEADERTYPE_EXPIRES);
                        if (expiresHeader != null && expiresHeader.flag && expiresHeader.headerValue != null && expiresHeader.headerValue.length() > 0) {
                            cmcore.expiresSeconds = Integer.parseInt(expiresHeader.headerValue.trim());
                        }
                    }

                    // SET REGISTERSTATE AS REGISTERED
                    if (cmcore.expiresSeconds > 0) {
                        cmcore.regTime = new Date();
                        cmcore.regState = SIPStack.SIP_REGSTATE_REGISTERED;
                        // Phone status set
                        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) {
                            // SERVICE MESSAGE NEEDED
                            updateDialerStatus("Ready.", false);
                        }

                        if (cmcore.action_reg_1(strMessage)) {
                            cmcore.regState = SIPStack.SIP_REGSTATE_UNREGISTERING;
                            sendUNRegister(cmcore.previfIp, cmcore.previfPort);
                        }
                    } else if (cmcore.expiresSeconds == 0) {
                        cmcore.regTime = new Date();
                        cmcore.regState = SIPStack.SIP_REGSTATE_IDLE;
                        // SERVICE MESSAGE NEEDED
                        updateDialerStatus("Service Off mode", false);
                    }
                }
                break;

            case 401:
                if (cmcore.repeatRegisterCount > 3) {
                    cmcore.regState = SIPStack.SIP_REGSTATE_UNAVAILABLE;
                    cmcore.repeatRegisterCount = 0;
                    // Phone status set
                    // SERVICE MESSAGE NEEDED
                    updateDialerStatus("Server 인증 실패하였습니다.", false);
                    break;
                }

                cmcore.regState = SIPStack.SIP_REGSTATE_UNAUTHORIZED;
                // Phone status set
                if (SIPController.sipCall.flag == false) {
                    // SERVICE MESSAGE NEEDED
                    updateDialerStatus("Regist Unauthorized.", false);
                }

                if (cmcore.action_reg_2(strMessage)) {
                    bSendRegister = true;
                    cmcore.repeatRegisterCount++;
                }
                break;

            case 407:
                if (cmcore.repeatRegisterCount > 3) {
                    cmcore.regState = SIPStack.SIP_REGSTATE_UNAVAILABLE;
                    cmcore.repeatRegisterCount = 0;
                    // Phone status set
                    // SERVICE MESSAGE NEEDED
                    updateDialerStatus("Server 인증 실패하였습니다.", false);
                    break;
                }

                // Phone status set
                // SERVICE MESSAGE NEEDED
                updateDialerStatus("Regist Unauthorized.", false);
                if (cmcore.action_reg_3(strMessage)) {
                    bSendRegister = true;
                }
                break;
            case 423:
                cmcore.action_reg_4(strMessage);
                sendRegister();
                break;

            default:
                if (requestLine.code >= 400) cmcore.regState = SIPStack.SIP_REGSTATE_UNAVAILABLE;
                break;
        }

        if (bSendRegister) {
            cmcore.regState = SIPStack.SIP_REGSTATE_AUTHORIZING;
            if (cmcore.authorizationH != null && cmcore.authorizationH.length() > 0)
                sendRegister();
        }
        return 0;   // normal
    }   // SIPParser()

    public void UPDATEParser(String message, int msgType, String remoteIp, int remotePort) {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false || (SIPController.sipCall.callMode != SIPStack.SIP_CALLMODE_BASIC && SIPController.sipCall.callMode != SIPStack.SIP_CALLMODE_HOLD)) {
            if (msgType == SIPStack.SIP_MSGTYPE_RESPONSE) {
                SIPRequestLine requestLine = new SIPRequestLine(message);
                if (requestLine != null && requestLine.flag && requestLine.code >= 300) {
                    sendFinalAck(message, remoteIp, remotePort);
                }
            }
            return;
        }

        if (msgType == SIPStack.SIP_MSGTYPE_REQUEST) {
            if (SIPController.sipCall != null) {
                if (SIPController.sipCall.flag) {
                    // busy
                    // validate call
                    SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
                    boolean bValidCall = false;
                    if (sipHeader != null && sipHeader.flag) {
                        if (sipHeader.headerValue != null && sipHeader.headerValue.length() > 0 && SIPController.sipCall.callId != null && sipHeader.headerValue.compareTo(SIPController.sipCall.callId) == 0) {
                            bValidCall = true;
                        }
                        //else Log.i("SIPStun", "Invalid call");
                    }

                    if (bValidCall) {
                        // EXIST CALL
                        // IF HOLDMODE
                        if (SIPController.sipCall.callMode == SIPStack.SIP_CALLMODE_HOLD) {
                            if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEOFFERRED) {
                                // ACCEPT
                            }
                            return;
                        } else if (SIPController.sipCall.callMode == SIPStack.SIP_CALLMODE_BASIC && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CONNECTED) {
                            // IF CONNECTED
                            //Log.i(TAG, "UPDATE MODE SET");
                            // SET CALLMODE AS UPDATE
                            SIPController.sipCall.callMode = SIPStack.SIP_CALLMODE_HOLD;
                            SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UPDATEOFFERRED;
                            SIPController.sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_IN;
                            //parse message + construct local and remote sdp +negotiate codec
                            if (SIPController.sipCall.constructUPDATEHeaders(message, remoteIp, remotePort)) {
                                // response trying
                                sendProceeding(remoteIp, remotePort);
                                if (false == sendUpdateAccept()) {
                                    rejectCall(message, 480, remoteIp, remotePort);
                                    return;
                                }
                            } else {
                                rejectCall(message, 480, remoteIp, remotePort);
                                return;
                            }
                            // ACCEPT
                            return;
                        } else {
                            // DISCARD
                            return;
                        }
                    } else {
                        // invalid update call
                        rejectCall(message, 400, remoteIp, remotePort);
                        return;
                    }
                } else {
                    // invalid update call
                    rejectCall(message, 400, remoteIp, remotePort);
                    return;
                }
            } else {
                // response 400
                // no sip call handle
                // response only
                rejectCall(message, 400, remoteIp, remotePort);
                return;
            }
        }   // if
        else if (msgType == SIPStack.SIP_MSGTYPE_RESPONSE && SIPController.sipCall.flag && SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_OUT) {
            if (SIPController.sipCall.callMode != SIPStack.SIP_CALLMODE_HOLD) return;
            SIPRequestLine requestLine = new SIPRequestLine(message);
            if (requestLine != null) {
                // validate call
                SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CALLID);
                boolean bValidCall = false;
                if (sipHeader != null && sipHeader.flag) {
                    if (sipHeader.headerValue != null && sipHeader.headerValue.length() > 0 && SIPController.sipCall.callId != null && sipHeader.headerValue.compareTo(SIPController.sipCall.callId) == 0) {
                        SIPHeader seqHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);
                        if (seqHeader != null && seqHeader.callSequenceNumber() == SIPController.sipCall.CSEQ_NUMBER) {
                            bValidCall = true;
                        } else if (requestLine.code < 200) {
                            return;
                        }
                    }
                }

                if (bValidCall) {
                    sipHeader = null;
                    sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_TO);

                    if (sipHeader != null) {
                        SIPController.sipCall.toH = sipHeader.header;
                        SIPController.sipCall.toTag = sipHeader.getTag();
                    }
                }

                sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CSEQ);

                if (bValidCall) {
                    SIPController.sipCall.remoteIp = remoteIp;
                    SIPController.sipCall.remotePort = remotePort;

                    if (requestLine.code >= 200 && sipHeader != null && sipHeader.flag) {
                        SIPController.sipCall.CSEQ_NUMBER = sipHeader.callSequenceNumber();
                    }

                    if (requestLine.code == 100) {
                        // trying
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UPDATEPROCEEDING;
                        SIPController.sipCall.callTime_T1 = new Date();
                    } else if (requestLine.code >= 180 && requestLine.code <= 183) {
                        // progressing
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UPDATEPROGRESSING;
                        SIPController.sipCall.callTime_T2 = new Date();

                        if (SIPController.sipCall.parseRemoteSdp(message)) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.flag) {
                                SIPController.sipCall.negotiateAudioCodec();
                            }

                            if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                                if (SIPController.sipCall.remoteSdp.audioM.flag) {
                                    if (SIPController.audioRTPManager != null) {
                                        SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);
                                        if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager.rtpCore.bActive == false) {
                                            SIPController.audioRTPManager.RTPInit(SIPController.sipCall.sdp.audioM.mediaPort);
                                        }
                                    }
                                }
                            }
                        }
                    } else if (requestLine.code == 200 && SIPController.sipCall.CSEQ_NUMBER == sipHeader.callSequenceNumber() &&
                            (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROCEEDING ||
                                    SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROGRESSING)) {
                        // connected
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UPDATEREMOTEACCEPTED;
                        SIPController.sipCall.callTime_T3 = new Date();
                        boolean ret = sendAck(message);

                        if (ret) {
                            SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_CONNECTED;
                            SIPController.sipCall.callMode = SIPStack.SIP_CALLMODE_BASIC;
                            SIPSound.resetBufferInfo();
                            // SERVICE MESSAGE NEEDED
                            dialerNotifyCallConnected(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                        }

                        // remote body analysis
                        // MUST BE CHANGE
                        if (SIPController.sipCall.parseRemoteSdp(message)) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.flag) {
                                SIPController.sipCall.negotiateAudioCodec();
                            }

                            if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                                if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                                    if (SIPController.audioRTPManager != null) {
                                        SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);
                                        if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager.rtpCore.bActive == false) {
                                            SIPController.audioRTPManager.RTPInit(SIPController.sipCall.sdp.audioM.mediaPort);
                                        }
                                    }
                                }
                            }
                        }
                    } else if (requestLine.code == 401 && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROCEEDING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROGRESSING)) {

                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UPDATEUNAUTHORIZED;
                        sendFinalAck(message);

                        if (reactionForWWWAUTHENTICATE(message) == false) {
                            Log.e(TAG, "[JEFF] ========== RTP END 25 ==========");
                            if (SIPController.audioRTPManager != null)
                                SIPController.audioRTPManager.RTPEnd();

                            SIPController.sipCall.resetCall();
                        }
                    } else if (requestLine.code == 407 && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROCEEDING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROGRESSING)) {
                        // Proxy-Athenticate
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UPDATEUNAUTHORIZED;
                        sendFinalAck(message);
                        if (reactionForPROXYAUTHENTICATE(message) == false) {
                            Log.e(TAG, "[JEFF] ========== RTP END 26 ==========");
                            if (SIPController.audioRTPManager != null)
                                SIPController.audioRTPManager.RTPEnd();

                            SIPController.sipCall.resetCall();
                        }
                    } else if (requestLine.code == 302 && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROCEEDING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROGRESSING)) {
                        // terminating
                        // FORWARD - MUST BE PROCESSED MORE
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_TERMINATING;
                        sendFinalAck(message);
                        Log.e(TAG, "[JEFF] ========== RTP END 27 ==========");
                        if (SIPController.audioRTPManager != null)
                            SIPController.audioRTPManager.RTPEnd();

                        SIPController.sipCall.resetCall();
                    } else if (requestLine.code >= 300 && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROCEEDING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEPROGRESSING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UPDATEUNAUTHORIZED)) {
                        // terminating
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_TERMINATING;
                        sendFinalAck(message);
                        Log.e(TAG, "[JEFF] ========== RTP END 28 ==========");
                        if (SIPController.audioRTPManager != null)
                            SIPController.audioRTPManager.RTPEnd();

                        SIPController.sipCall.resetCall();
                    }
                } else {
                    sendFinalAck(message, remoteIp, remotePort);
                }
            }   // if
        }   // else if
        return;
    }

    public void INVITEParser(String strMessage, int nMSGType, String strRemoteIP, int strRemotePort) {
        try {
            if (nMSGType == SIPStack.SIP_MSGTYPE_REQUEST) {
                if (SIPController.sipCall != null) {
                    Log.e(TAG, "[INVITEParser] ==================== JEFF [SIPController.sipCall.flag = " + SIPController.sipCall.flag + "] ====================");

                    SIPController.sipCall.flag = false;
                    if (SIPController.sipCall.flag) {
                        // busy
                        Log.e(TAG, "[INVITEParser] ==================== JEFF [1] ====================");

                        boolean bValidCall = SIPController.sipCall.isCurrentCall(strMessage);
                        Log.e(TAG, "[INVITEParser] bValidCall = " + bValidCall);

                        if (bValidCall) {
                            //EXIST CALL
                            //IF HOLDEMODE
                            if (SIPController.sipCall.callMode == SIPStack.SIP_CALLMODE_HOLD) {
                                Log.e(TAG, "[INVITEParser] ==================== JEFF [2] ====================");
                                UPDATEParser(strMessage, nMSGType, strRemoteIP, strRemotePort);
                                return;
                            } else if (SIPController.sipCall.callMode == SIPStack.SIP_CALLMODE_BASIC && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CONNECTED) {
                                // IF CONNECTED
                                // UPDATE PROCESSING
                                Log.e(TAG, "[INVITEParser] ==================== JEFF [3] ====================");
                                UPDATEParser(strMessage, nMSGType, strRemoteIP, strRemotePort);
                                return;
                            } else {
                                // DISCARD
                                Log.e(TAG, "[INVITEParser] ==================== JEFF [4] ====================");
                                return;
                            }
                        } else {
                            Log.i(TAG, "BUSY CHECK : callState : " + SIPController.sipCall.callState);

                            if (SIPController.sipCall.callState != SIPStack.SIP_CALLSTATE_CONNECTED) {
                                Log.e(TAG, "[INVITEParser] ==================== JEFF [486] 1 ====================");
                                rejectCall(strMessage, 486, strRemoteIP, strRemotePort);
                                return;
                            }

                            if (SIPController.bMulticallSupport) {
                                if (SIPController.pendingCall != null) {
                                    if (SIPController.pendingCall.flag) {
                                        if (SIPController.pendingCall.isCurrentCall(strMessage)) {
                                            // pendingCall self
                                            // no action
                                        } else {
                                            // pendingCall exist and another pending call incoming
                                            Log.e(TAG, "[INVITEParser] ==================== JEFF [486] 2 ====================");
                                            rejectCall(strMessage, 486, strRemoteIP, strRemotePort);
                                        }
                                        return;
                                    } else {
                                        // New incoming pending call
                                        if (CMCore.bDialerActive == false) {
                                            Log.e(TAG, "[INVITEParser] ==================== JEFF [486] 3 ====================");
                                            rejectCall(strMessage, 486, strRemoteIP, strRemotePort);
                                            return;
                                        }

                                        // pending call construct
                                        String fromId = null;
                                        String toId = null;
                                        SIPHeader sipHeader = new SIPHeader(strMessage, SIPStack.SIP_HEADERTYPE_TO);
                                        if (sipHeader != null && sipHeader.flag) {
                                            toId = sipHeader.getId().trim();
                                            if (toId != null && toId.length() > 0) {
                                                sipHeader = new SIPHeader(strMessage, SIPStack.SIP_HEADERTYPE_FROM);
                                                if (sipHeader != null && sipHeader.flag) {
                                                    fromId = sipHeader.getId().trim();
                                                }
                                            }

                                            if (cmcore.id != null && toId.compareTo(cmcore.id) == 0) {
                                                // activate call handler
                                                boolean ret = false;
                                                if (SIPStack.bDirectCall == false) {
                                                    if (strRemoteIP.compareTo(cmcore.serverIp) == 0) {
                                                        ret = SIPController.pendingCall.activeCallHandle(cmcore.id, cmcore.cid, cmcore.authid, cmcore.authpassword, fromId, strRemoteIP, strRemotePort, cmcore.serverDomain, cmcore.localIp, cmcore.localPort);
                                                    } else {
                                                        ret = SIPController.pendingCall.activeCallHandle(cmcore.id, cmcore.cid, cmcore.authid, cmcore.authpassword, fromId, strRemoteIP, strRemotePort, strRemoteIP, cmcore.localIp, cmcore.localPort);
                                                    }
                                                } else {
                                                    ret = SIPController.pendingCall.activeCallHandle(cmcore.id, cmcore.cid, cmcore.authid, cmcore.authpassword, fromId, strRemoteIP, strRemotePort, strRemoteIP, cmcore.localIp, cmcore.localPort);
                                                }

                                                if (ret) {
                                                    SIPController.pendingCall.callState = SIPStack.SIP_CALLSTATE_OFFERRED;
                                                    SIPController.pendingCall.callDirection = SIPStack.SIP_CALLDIRECTION_IN;
                                                    SIPController.pendingCall.callTime_T7 = new Date();//offerred timer
                                                    if (SIPController.pendingCall.constructHeaders(strMessage, strRemoteIP, strRemotePort)) {
                                                        sendPendingProceeding(strRemoteIP, strRemotePort);
                                                        dialerNotifyIncomingMultiCall(SIPController.pendingCall.dnis, SIPController.pendingCall.dnis + "@" + SIPController.pendingCall.remoteIp + ":" + SIPController.pendingCall.remotePort);
                                                    } else {
                                                        Log.e(TAG, "[INVITEParser] ==================== JEFF [480] 4 ====================");
                                                        rejectCall(strMessage, 480, strRemoteIP, strRemotePort);
                                                        return;
                                                    }
                                                } else {
                                                    Log.e(TAG, "[INVITEParser] ==================== JEFF [480] 5 ====================");
                                                    rejectCall(strMessage, 480, strRemoteIP, strRemotePort);
                                                    return;
                                                }
                                                sendPendingProgressing(strRemoteIP, strRemotePort);
                                                return;
                                            } else {
                                                Log.e(TAG, "[INVITEParser] ==================== JEFF [404] 6 ====================");
                                                rejectCall(strMessage, 404, strRemoteIP, strRemotePort);
                                                return;
                                            }
                                        } else {
                                            Log.e(TAG, "[INVITEParser] ==================== JEFF [486] 7 ====================");
                                            rejectCall(strMessage, 486, strRemoteIP, strRemotePort);
                                        }
                                    }
                                } else {
                                    Log.e(TAG, "[INVITEParser] ==================== JEFF [486] 8 ====================");
                                    rejectCall(strMessage, 486, strRemoteIP, strRemotePort);
                                }
                            } else {
                                // BUSY
                                Log.e(TAG, "[INVITEParser] ==================== JEFF [486] 9 ====================");
                                rejectCall(strMessage, 486, strRemoteIP, strRemotePort);
                            }
                        }
                    } else {
                        Log.e(TAG, "[INVITEParser] ==================== JEFF [100] ====================");
                        // BUSY UPDATE END
                        // processing inviting call
                        SIPStun.bBlackCall = false;
                        String fromId = null;
                        String toId = null;
                        SIPHeader sipHeader = new SIPHeader(strMessage, SIPStack.SIP_HEADERTYPE_TO);
                        if (sipHeader != null && sipHeader.flag) {

                            Log.d(TAG, "[INVITEParser] toId [" + sipHeader.header + "]");
                            if(!sipHeader.header.contains("@"))
                            {
                                toId = sipHeader.header.substring(9, sipHeader.header.length()-1).trim();
                                sipHeader = new SIPHeader(strMessage, SIPStack.SIP_HEADERTYPE_FROM);
                                Log.d(TAG, "[INVITEParser] fromId [" + sipHeader.header + "]");
                                String[] strSplit = sipHeader.header.split("@");
                                fromId = strSplit[0].substring(7, strSplit[0].length()).trim();
                            }
                            else
                            {
                                toId = sipHeader.getId().trim();
                                if (toId != null && toId.length() > 0) {
                                    sipHeader = new SIPHeader(strMessage, SIPStack.SIP_HEADERTYPE_FROM);
                                    if (sipHeader != null && sipHeader.flag) {
                                        fromId = sipHeader.getId().trim();
                                    }
                                }
                            }

                            Log.d(TAG, "[INVITEParser] cmcore.id [" + cmcore.id + "], toId [" + toId + "]");
                            Log.d(TAG, "[INVITEParser] cmcore.id [" + cmcore.id + "], toId [" + fromId + "]");
                            toId = MainActivity.mCallController.makeSIPID(toId);
                            fromId = MainActivity.mCallController.makeSIPID(fromId);
                            if (cmcore.id != null && toId.compareTo(cmcore.id) == 0) {
                                // activate call handler
                                boolean ret = false;
                                if (SIPStack.bDirectCall == false) {
                                    if (strRemoteIP.compareTo(cmcore.serverIp) == 0) {
                                        ret = SIPController.sipCall.activeCallHandle(cmcore.id, cmcore.cid, cmcore.authid, cmcore.authpassword, fromId, strRemoteIP, strRemotePort, cmcore.serverDomain, cmcore.localIp, cmcore.localPort);
                                    } else {
                                        ret = SIPController.sipCall.activeCallHandle(cmcore.id, cmcore.cid, cmcore.authid, cmcore.authpassword, fromId, strRemoteIP, strRemotePort, strRemoteIP, cmcore.localIp, cmcore.localPort);
                                    }
                                } else {
                                    if (CMCore.bDialerActive == false) {
                                        Log.i(TAG, ">>>>> New call. Dialer awaken.");
                                        Context context = SIPStun.this;//Contexts.SERVICE;
                                        Intent intent = new Intent(context, V40IFCCD.class);
                                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                                        context.startActivity(intent);
                                        SIPStun.bBlackCall = true;

                                        if (SIPStun.bBlackCallBackgroundMode) {
                                            ret = SIPController.sipCall.activeCallHandle(cmcore.id, cmcore.cid, cmcore.authid, cmcore.authpassword, fromId, strRemoteIP, strRemotePort, strRemoteIP, cmcore.localIp, cmcore.localPort);

                                            if (ret) {
                                                SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_OFFERRED;
                                                SIPController.sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_IN;
                                                SIPController.sipCall.callTime_T7 = new Date();   // offerred timer
                                                // parse message + construct local and remote sdp +negotiate codec
                                                if (SIPController.sipCall.constructHeaders(strMessage, strRemoteIP, strRemotePort)) {
                                                    // response trying
                                                    sendProceeding(strRemoteIP, strRemotePort);
                                                    SIPController.sipCall.bResponsebackgroundcall = true;
                                                    SIPController.sipCall.bResponsebackgroundcallReady = false;

                                                    if (SIPController.sipCall.hnsOriginatorServiceType == BSSVideo.HNS_SERVICE_LOBBY) {
                                                        SIPController.latestMenu = 1;
                                                    } else if (SIPController.sipCall.hnsOriginatorServiceType == BSSVideo.HNS_SERVICE_GUARD) {
                                                        SIPController.latestMenu = 2;
                                                    } else if (SIPController.sipCall.hnsOriginatorServiceType == BSSVideo.HNS_SERVICE_NEIGHBOR) {
                                                        SIPController.latestMenu = 3;
                                                    }

                                                    if (BSSVideo.bProgressvideooffer || SIPController.forward.bForward) {
                                                        sendProgressingBlackcallwithbody(strRemoteIP, strRemotePort);
                                                    } else {
                                                        sendProgressing(strRemoteIP, strRemotePort);
                                                    }
                                                }
                                            }
                                        }
                                        return;
                                    }

                                    ret = SIPController.sipCall.activeCallHandle(cmcore.id, cmcore.cid, cmcore.authid, cmcore.authpassword, fromId, strRemoteIP, strRemotePort, strRemoteIP, cmcore.localIp, cmcore.localPort);
                                }

                                if (ret) {
                                    SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_OFFERRED;
                                    SIPController.sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_IN;
                                    SIPController.sipCall.callTime_T7 = new Date();//offerred timer
                                    //parse message + construct local and remote sdp +negotiate codec
                                    if (SIPController.sipCall.constructHeaders(strMessage, strRemoteIP, strRemotePort)) {
                                        // response trying
                                        sendProceeding(strRemoteIP, strRemotePort);
                                        updateDialerStatus("전화가 왔습니다.", false);
                                        dialerNotifyIncomingCall(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                                    } else {
                                        rejectCall(strMessage, 480, strRemoteIP, strRemotePort);
                                        updateDialerStatus("전화를 종료했습니다.", false);
                                        return;
                                    }
                                } else {
                                    rejectCall(strMessage, 480, strRemoteIP, strRemotePort);
                                    return;
                                }

                                if (BSSVideo.bProgressvideooffer || SIPController.forward.bForward) {
                                    sendProgressingwithbody(strRemoteIP, strRemotePort);
                                } else {
                                    sendProgressing(strRemoteIP, strRemotePort);
                                }
                            } else {
                                rejectCall(strMessage, 404, strRemoteIP, strRemotePort);
                                return;
                            }
                        }
                    }
                } else {
                    // response 480
                    // no sip call handle
                    // response only
                    rejectCall(strMessage, 480, strRemoteIP, strRemotePort);
                }
            }   // if
            else if (nMSGType == SIPStack.SIP_MSGTYPE_RESPONSE) {

                if (cmcore.INVITEParser_action_0(SIPController.sipCall, strMessage)) {
                    SIPHeader sipHeader = null;
                    sipHeader = new SIPHeader(strMessage, SIPStack.SIP_HEADERTYPE_TO);

                    if (sipHeader != null) {
                        SIPController.sipCall.toH = sipHeader.header;
                        SIPController.sipCall.toTag = sipHeader.getTag();
                    }

                    sipHeader = new SIPHeader(strMessage, SIPStack.SIP_HEADERTYPE_CSEQ);

                    if (SIPController.sipCall.callMode == SIPStack.SIP_CALLMODE_HOLD) {
                        UPDATEParser(strMessage, nMSGType, strRemoteIP, strRemotePort);
                        return;
                    }

                    SIPController.sipCall.remoteIp = strRemoteIP;
                    SIPController.sipCall.remotePort = strRemotePort;
                    if (SIPController.sipCall.responseCode >= 200 && sipHeader != null && sipHeader.flag) {
                        SIPController.sipCall.CSEQ_NUMBER = sipHeader.callSequenceNumber();
                    }

                    if (SIPController.sipCall.responseCode == 100) {
                        // trying
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_PROCEEDING;
                        SIPController.sipCall.callTime_T1 = new Date();
                        // Phone status set
                        // SERVICE MESSAGE NEEDED
                        updateDialerStatus("Call proceeding.", false);
                    } else if (SIPController.sipCall.responseCode >= 180 && SIPController.sipCall.responseCode <= 183) {
                        // progressing
                        // SERVICE MESSAGE NEEDED
                        dialerNotifyRingbackTone(true);
                        // Phone status set
                        // SERVICE MESSAGE NEEDED
                        updateDialerStatus("Call progressing.", false);

                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_PROGRESSING;
                        SIPController.sipCall.callTime_T2 = new Date();
                        if (SIPController.sipCall.parseRemoteSdp(strMessage)) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.flag) {
                                SIPController.sipCall.negotiateAudioCodec();
                            }

                            if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                                if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                                    if (SIPController.audioRTPManager != null) {
                                        SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);
                                        if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager.rtpCore.bActive == false) {
                                            if (SIPStack.bDirectCall && BSSVideo.bProgressvideooffer) {
                                                // SERVICE MESSAGE NEEDED
                                                dialerVideoSet(true);
                                            } else {
                                                SIPController.audioRTPManager.RTPInit(SIPController.sipCall.sdp.audioM.mediaPort);
                                            }
                                        }
                                    }
                                }
                            }
                        } else {
                            // local ringbacktone play
                            // SERVICE MESSAGE NEEDED
                            dialerNotifyRingbackTone(true);
                        }
                    } else if (SIPController.sipCall.responseCode == 200 && SIPController.sipCall.CSEQ_NUMBER == sipHeader.callSequenceNumber() &&
                            (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_INVITING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROCEEDING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROGRESSING)) {
                        // connected
                        // Phone status set
                        // SERVICE MESSAGE NEEDED
                        updateDialerStatus("Connected.", false);
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_REMOTEACCEPTED;
                        SIPController.sipCall.callTime_T3 = new Date();
                        boolean ret = sendAck(strMessage);

                        if (ret) {
                            SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_CONNECTED;
                            SIPController.sipCall.callTime_T4 = new Date();
                            SIPController.sipCall.callTime_T40 = new Date();
                            SIPSound.resetBufferInfo();
                            // SERVICE MESSAGE NEEDED
                            dialerNotifyCallConnected(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                        }
                        if (SIPController.sipCall.parseRemoteSdp(strMessage)) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.flag) {
                                SIPController.sipCall.negotiateAudioCodec();
                            }

                            if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                                if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                                    if (SIPController.audioRTPManager != null) {
                                        SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);
                                        if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager.rtpCore.bActive == false) {
                                            if (SIPStack.bDirectCall) {
                                                SIPController.audioRTPManager.RTPInit(SIPController.sipCall.sdp.audioM.mediaPort);
                                                // SERVICE MESSAGE NEEDED
                                                dialerVideoSet(true);
                                            } else {
                                                SIPController.audioRTPManager.RTPInit(SIPController.sipCall.sdp.audioM.mediaPort);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    } else if (SIPController.sipCall.responseCode == 401 && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_INVITING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROCEEDING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROGRESSING)) {
                        // WWW-Athenticate
                        // Phone status set
                        // SERVICE MESSAGE NEEDED
                        updateDialerStatus("Call Unauthorized(401).", false);
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UNAUTHORIZED;
                        SIPController.sipCall.authorizationACKH = "";

                        sendFinalAck(strMessage);
                        if (reactionForWWWAUTHENTICATE(strMessage) == false) {
                            Log.e(TAG, "[JEFF] ========== RTP END 8 ==========");
                            if (SIPController.audioRTPManager != null)
                                SIPController.audioRTPManager.RTPEnd();
                            if (SIPStack.bDirectCall) {
                                // SERVICE MESSAGE NEEDED
                                dialerVideoSet(false);
                            }

                            dialerNotifyCallFail(SIPController.sipCall.responseCode, SIPController.sipCall.remoteIp);
                            //SERVICE MESSAGE NEEDED
                            dialerNotifyCallEnd("Call Unauthorized(401).", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
                            SIPController.sipCall.resetCall();
                        }
                    } else if (SIPController.sipCall.responseCode == 407 && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_INVITING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROCEEDING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROGRESSING)) {
                        // Proxy-Athenticate
                        // Phone status set
                        // SERVICE MESSAGE NEEDED
                        updateDialerStatus("Call Unauthorized(407).", false);

                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UNAUTHORIZED;
                        SIPController.sipCall.authorizationACKH = "";

                        sendFinalAck(strMessage);

                        if (reactionForPROXYAUTHENTICATE(strMessage) == false) {
                            Log.e(TAG, "[JEFF] ========== RTP END 9 ==========");
                            if (SIPController.audioRTPManager != null)
                                SIPController.audioRTPManager.RTPEnd();
                            if (SIPStack.bDirectCall) {
                                //SERVICE MESSAGE NEEDED
                                dialerVideoSet(false);
                            }

                            dialerNotifyCallFail(SIPController.sipCall.responseCode, SIPController.sipCall.remoteIp);

                            // SERVICE MESSAGE NEEDED
                            dialerNotifyCallEnd("Call Unauthorized(407).", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
                            SIPController.sipCall.resetCall();
                        }
                    } else if (SIPController.sipCall.responseCode == 302 && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_INVITING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROCEEDING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROGRESSING)) {
                        // terminating
                        // SERVICE MESSAGE NEEDED
                        Log.e(TAG, "[INVITEParser] ===== JEFF 1 START =====");
                        LOG_ERROR("[INVITEParser] BSSVideo.HNS_SERVICE_RECEIVER_SELECTED [" + BSSVideo.HNS_SERVICE_RECEIVER_SELECTED + "]");
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.remoteIp : " + SIPController.sipCall.remoteIp);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.number : " + SIPController.sipCall.number);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.cid : " + SIPController.sipCall.cid);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.dnis : " + SIPController.sipCall.dnis);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.dong_number : " + SIPController.sipCall.dong_number);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.ho_number : " + SIPController.sipCall.ho_number);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.id : " + SIPController.sipCall.id);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.remoteContactUri : " + SIPController.sipCall.remoteContactUri);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.remoteContactPort : " + SIPController.sipCall.remoteContactIp);
                        LOG_ERROR("[INVITEParser] SIPController.sipCall.remoteContactPort : " + SIPController.sipCall.remoteContactPort);
                        Log.e(TAG, "[INVITEParser] ===== JEFF 1 END =====");

                        SIPCONTACTHeader contactHeader = new SIPCONTACTHeader(strMessage);
                        updateDialerStatus("Call forwarded./" + contactHeader.getSipuri(), true);
                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_REDIRECTED;

                        sendRedirectFinalAck(strMessage);

                        Log.e(TAG, "[JEFF] ========== RTP END 10 ==========");
                        if (SIPController.audioRTPManager != null)
                            SIPController.audioRTPManager.RTPEnd();
                        if (SIPStack.bDirectCall) {
                            dialerVideoSet(false);
                        }
                        SIPController.sipCall.resetCall();
                    } else if (SIPController.sipCall.responseCode >= 300 && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_INVITING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROCEEDING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROGRESSING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_UNAUTHORIZED ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CANCELLING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_RECANCELLING ||
                            SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CANCELREMOTEACCEPTED)) {
                        // terminating
                        // Phone status set
                        // SERVICE MESSAGE NEEDED
                        updateDialerStatus("Call rejected by remoter.", true);

                        SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_TERMINATING;
                        sendFinalAck(strMessage);
                        Log.e(TAG, "[JEFF] ========== RTP END 12 ==========");
                        if (SIPController.audioRTPManager != null)
                            SIPController.audioRTPManager.RTPEnd();
                        if (SIPStack.bDirectCall) {
                            // SERVICE MESSAGE NEEDED
                            dialerVideoSet(false);
                        }

                        dialerNotifyCallFail(SIPController.sipCall.responseCode, SIPController.sipCall.remoteIp);
                        // SERVICE MESSAGE NEEDED
                        dialerNotifyCallEnd("Call rejected by remoter.", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
                        SIPController.sipCall.resetCall();
                    } else {
                        Log.e(TAG, "[INVITEParser] ========== else 1 ==========");
                    }
                }   // if
                else {
                    Log.e(TAG, "[INVITEParser] ========== else 2 ==========");
                }
            }   //else if
            else {
                Log.e(TAG, "[INVITEParser] ========== else 3 ==========");
            }
        } catch (Exception e) {
            Log.e(TAG, "[Exception] INVITEParser(String message, int msgType, String remoteIp, int remotePort)");
            e.printStackTrace();
        }
    }

    public void ACKParser(String message, int msgType, String remoteIp, int remotePort) {
        boolean bValid = false;
        if (SIPController.sipCall != null && SIPController.sipCall.flag) {
            bValid = SIPController.sipCall.isCurrentCall(message);
        }

        if (bValid) {
            if (msgType == SIPStack.SIP_MSGTYPE_REQUEST && SIPController.sipCall.flag && SIPController.sipCall.callMode == SIPStack.SIP_CALLMODE_HOLD) {
                if (cmcore.ACKParser_action_0(SIPController.sipCall, message)) {
                    SIPSound.resetBufferInfo();
                    // SERVICE MESSAGE NEEDED
                    dialerNotifyCallConnected(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                }
            } else if (msgType == SIPStack.SIP_MSGTYPE_REQUEST && SIPController.sipCall.flag && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_ACCEPTED) {
                if (cmcore.ACKParser_action_1(SIPController.sipCall, message)) {
                    // SERVICE MESSAGE NEEDED
                    updateDialerStatus("Connected.", false);
                    SIPSound.resetBufferInfo();
                    // SERVICE MESSAGE NEEDED
                    dialerNotifyCallConnected(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                }
            } else if (msgType == SIPStack.SIP_MSGTYPE_REQUEST && SIPController.sipCall.flag && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CANCELLED ||
                    SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_TERMINATING)) {
                //Log.i(TAG, "ACK arrived.");
                if (cmcore.ACKParser_action_2(SIPController.sipCall, message)) {
                    Log.e(TAG, "[JEFF] ========== RTP END 1 ==========");
                    if (SIPController.audioRTPManager != null)
                        SIPController.audioRTPManager.RTPEnd();
                    if (SIPStack.bDirectCall) {
                        // SERVICE MESSAGE NEEDED
                        dialerVideoSet(false);
                    }
                    // SERVICE MESSAGE NEEDED
                    dialerNotifyCallEnd("", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
                    SIPController.sipCall.resetCall();
                }
            }
            return;
        }

        if (SIPController.pendingCall != null && SIPController.pendingCall.flag) {
            bValid = SIPController.pendingCall.isCurrentCall(message);
        }

        if (bValid) {
            if (msgType == SIPStack.SIP_MSGTYPE_REQUEST && SIPController.pendingCall.flag && (SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_CANCELLED ||
                    SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_TERMINATING)) {
                SIPController.pendingCall.resetCall();
            }
        }
        return;
    }

    public void CANCELParser(String message, int msgType, String remoteIp, int remotePort) {
        boolean bValid = false;
        if (SIPController.sipCall != null && SIPController.sipCall.flag) {
            bValid = SIPController.sipCall.isCurrentCall(message);
        }

        if (bValid) {
            if (msgType == SIPStack.SIP_MSGTYPE_REQUEST && SIPController.sipCall.flag && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
                if (cmcore.CANCELParser_action_0(SIPController.sipCall, message)) {
                    acceptCancelRequest(message, remoteIp, remotePort);

                    if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                        if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                                Log.e(TAG, "[JEFF] ========== RTP END 7 ==========");
                                SIPController.audioRTPManager.RTPEnd();
                                if (SIPStack.bDirectCall) {
                                    // SERVICE MESSAGE NEEDED
                                    dialerVideoSet(false);
                                }
                            }
                        }
                    }
                    rejectCall(487);
                }
            } else if (msgType == SIPStack.SIP_MSGTYPE_RESPONSE && SIPController.sipCall.flag && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CANCELLING ||
                    SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_RECANCELLING)) {
                if (cmcore.CANCELParser_action_1(SIPController.sipCall, message)) {
                    // MORE CODE NEEDED ... 2014 08 19
                    SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_CANCELREMOTEACCEPTED;
                    // none action
                }
            }
            return;
        }

        // Multicall
        if (SIPController.pendingCall != null && SIPController.pendingCall.flag) {
            bValid = SIPController.pendingCall.isCurrentCall(message);
        }

        if (bValid) {
            if (msgType == SIPStack.SIP_MSGTYPE_REQUEST && SIPController.pendingCall.flag && SIPController.pendingCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
                if (cmcore.CANCELParser_action_0(SIPController.pendingCall, message)) {
                    acceptPendingCancelRequest(message, remoteIp, remotePort);
                    rejectPendingCall(487);
                    dialerNotifyMulticallCancel();
                }
            }
            return;
        }
    }

    public void BYEParser(String message, int msgType, String remoteIp, int remotePort) {
        if (msgType == SIPStack.SIP_MSGTYPE_REQUEST && SIPController.sipCall.flag && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_ACCEPTED ||
                SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_REMOTEACCEPTED ||
                SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CONNECTED)) {
            if (cmcore.action_bye_0(SIPController.sipCall, message)) {
                Log.e(TAG, "[JEFF] ========== RTP END 2 ==========");
                if (SIPController.audioRTPManager != null)
                    SIPController.audioRTPManager.RTPEnd();
                if (SIPStack.bDirectCall) {
                    // SERVICE MESSAGE NEEDED
                    dialerVideoSet(false);
                }

                int duration = 0;
                Date currentTime = new Date();
                if (SIPController.sipCall.callTime_T4 != null) {
                    duration = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T4.getTime()) / 1000;
                    if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN)
                        duration -= 1;
                    if (duration < 0) duration = 0;
                }

                sendByeResponse(message, remoteIp, remotePort);

                dialerNotifyCallFail(700, SIPController.sipCall.remoteIp);

                //SERVICE MESSAGE NEEDED
                updateDialerStatus("상대가 전화를 끊었습니다.", false);
                //SERVICE MESSAGE NEEDED
                dialerNotifyCallEnd("상대가 전화를 끊었습니다.", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
            }
        } else if (msgType == SIPStack.SIP_MSGTYPE_RESPONSE && SIPController.sipCall.flag && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_DISCONNECTING) {
            if (cmcore.action_bye_1(SIPController.sipCall, message)) {
                Log.e(TAG, "[JEFF] ========== RTP END 3 ==========");
                if (SIPController.audioRTPManager != null) SIPController.audioRTPManager.RTPEnd();
                if (SIPStack.bDirectCall) {
                    // SERVICE MESSAGE NEEDED
                    dialerVideoSet(false);
                }
                // SERVICE MESSAGE NEEDED
                updateDialerStatus("Ready.", true);
                // SERVICE MESSAGE NEEDED
                dialerNotifyCallEnd("Ready.", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
            }
        }
        return;
    }

    public int SIPParser(String strMessage, int nMSGType, int nMethodType, String strRemoteIP, int strRemotePort) {
        try {
            if (bPrintSIPMsgIO) {
                Log.i(TAG, "[SIPParser] nMSGType [" + nMSGType + "], nMethodType [" + nMethodType + "], strRemoteIP [" + strRemoteIP + "], strRemotePort [" + strRemotePort + "]");
                printSIPMessage(MESSAGE.RECEIVE, strMessage);
            }

            if (nMethodType == SIPStack.SIP_METHODTYPE_INVITE) {
                // INVITE MESSAGE PROCESSING
                INVITEParser(strMessage, nMSGType, strRemoteIP, strRemotePort);
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_ACK) {
                // ACK MESSAGE PROCESSING
                ACKParser(strMessage, nMSGType, strRemoteIP, strRemotePort);
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_OPTIONS) {
                // OPTIONS MESSAGE PROCESSING
                if (nMSGType == SIPStack.SIP_MSGTYPE_REQUEST) {
                    sendOptionsResponse(strMessage, strRemoteIP, strRemotePort, 200);
                }
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_INFO) {
                // INFO MESSAGE PROCESSING
                if (cmcore.action_info_0(SIPController.sipCall, strMessage, nMSGType)) {
                    sendInfoResponse(strMessage, strRemoteIP, strRemotePort, 200);
                }
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_CANCEL) {
                // CANCEL MESSAGE PROCESSING
                CANCELParser(strMessage, nMSGType, strRemoteIP, strRemotePort);
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_BYE) {
                // BYE MESSAGE PROCESSING
                BYEParser(strMessage, nMSGType, strRemoteIP, strRemotePort);
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_REFER) {
                // REFER
                // IF NEED,CODING NEEDED
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_NOTIFY) {
                // NOTIFY
                // IF NEED,CODING NEEDED
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_MESSAGE) {
                // MESSAGE
                if (nMSGType == SIPStack.SIP_MSGTYPE_REQUEST) {
                    sendMessageResponse(strMessage, strRemoteIP, strRemotePort, 200);
                }
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_SUBSCRIBE) {
                // SUBSCRIBE
                // IF NEED,CODING NEEDED
            } else if (nMethodType == SIPStack.SIP_METHODTYPE_PRACK) {
                // PRACK
                // IF NEED,CODING NEEDED
            }
            return 0;
        } catch (Exception e) {
            Log.e(TAG, "SIPParser(String strMessage, int nMSGType, int nMethodType, String strRemoteIP, int strRemotePort)");
            e.printStackTrace();
            return -1;
        }
    }

    public void registRTPManager(RTPManager rtpmanager, int mediaType) {
        if (mediaType == SIPStack.SIP_MEDIATYPE_AUDIO) {
            SIPController.audioRTPManager = rtpmanager;
            if (SIPStack.SIP_MESSAGE_DEBUG)
                Log.i(TAG, "AUDIO RTPMANAGER SET Notified to RegisterManager.");
        }
    }

    public boolean sendRegister() {
        if (cmcore.makeRegister()) {
            if (cmcore.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = cmcore.message.getBytes();

                if (cmcore.message.length() > 0) {

                    if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, cmcore.message);
//		            if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + cmcore.message);

                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(cmcore.serverIp, cmcore.serverPort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }
                    cmcore.regTime = new Date();
                }
            }
            return true;
        }
        return false;
    }

    public boolean sendUNRegister() {
        if (cmcore.makeUNRegister()) {
            if (cmcore.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = cmcore.message.getBytes();

                if (cmcore.message.length() > 0) {

                    if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, cmcore.message);
//					if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + cmcore.message);

                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(cmcore.serverIp, cmcore.serverPort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }
                    cmcore.regTime = new Date();
                }
            }
            return true;
        }
        return false;
    }

    public boolean sendUNRegister(String contactip, int contactport) {
        if (cmcore.makeUNRegister(contactip, contactport)) {
            if (cmcore.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = cmcore.message.getBytes();
                if (cmcore.message.length() > 0) {

                    if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, cmcore.message);
//	                if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + cmcore.message);

                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(cmcore.serverIp, cmcore.serverPort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }
                    cmcore.regTime = new Date();
                }
            }
            return true;
        }
        return false;
    }

    public boolean decideRegister() {
        Date currentDate = new Date();
        int seconds = (int) (currentDate.getTime() - cmcore.regTime.getTime()) / 1000;
        if (seconds > cmcore.expiresSeconds - 10) return true;
        else return false;
    }

    public boolean callActivate(String number) {
        if (SIPController.sipCall == null) return false;

        String dial = "";

        if (SIPController.sipCall.flag == false) {
            // Phone status set
            // SERVICE MESSAGE NEEDED
            updateDialerStatus("Calling to " + number, false);

            if (number.length() > 32) {
                dial = number.substring(0, 32);
            } else {
                dial = new String(number);
            }
            return callMake(dial);
        } else if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
            // Phone status set
            // SERVICE MESSAGE NEEDED
            updateDialerStatus("Incoming call accept.", false);
            return sendAccept();
        }
        return false;
    }

    public boolean directcallActivate(String strNumber) {
        try {
            LOG_DEBUG("[directcallActivate] strNumber [" + strNumber + "]");
            if (SIPController.sipCall == null) {
                LOG("[directcallActivate] SIPController.sipCall is null!!");
                return false;
            }
            String dial = "";
            LOG_DEBUG("[directcallActivate] SIPController.sipCall.flag = " + SIPController.sipCall.flag);
            if (SIPController.sipCall.flag == false) {
                // Phone status set
                // SERVICE MESSAGE NEEDED
                updateDialerStatus("Calling to " + strNumber, false);

                if (strNumber.length() > 32) {
                    dial = strNumber.substring(0, 32);
                } else {
                    dial = new String(strNumber);
                }
                return directcallMake(dial);
            } else if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
                // Phone status set
                // SERVICE MESSAGE NEEDED
                updateDialerStatus("Incoming call accept.", false);
                return directsendAccept();
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] directcallActivate(String strNumber)");
            e.printStackTrace();
            return false;
        }
    }

    public boolean callMake(String number) {
        if (cmcore.regState != SIPStack.SIP_REGSTATE_REGISTERED) {
            // SERVICE MESSAGE NEEDED
            dialerNotifyCallEnd("Not registered.", "", "", true);
            return false;
        }

        if (cmcore.makeCallMake(SIPController.sipCall, number)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();
                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);
                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }

                SIPController.sipCall.callTime_T0 = new Date();
                SIPController.sipCall.callTime_T00 = new Date();
                SIPController.sipCall.invitingTimes++;
                return true;
            }
        }
        return false;
    }

    public boolean directcallMake(String number) {
        if (SIPController.sipCall == null || SIPController.sipCall.flag) return false;

        if (cmcore.makeDirectcallMake(SIPController.sipCall, number)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//		        if(SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        // INVITING
                        break;
                    }
                    repeatSendCount++;
                }

                SIPController.sipCall.callTime_T0 = new Date();
                SIPController.sipCall.callTime_T00 = new Date();
                SIPController.sipCall.invitingTimes++;

            }
            return true;
        }
        return false;
    }

    public boolean sendReInvite() {
        if (cmcore.makeSendReInvite(SIPController.sipCall)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//			    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);
                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }

                SIPController.sipCall.callTime_T00 = new Date();
                SIPController.sipCall.invitingTimes++;
                return true;
            }
        }
        return false;
    }

    public boolean sendRepeatInvite() {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) return false;

        if (SIPController.sipCall.message == null || SIPController.sipCall.message.length() == 0)
            return false;

        if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = SIPController.sipCall.message.getBytes();
            if (SIPController.sipCall.message.length() > 0) {

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//			    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
                SIPController.sipCall.callTime_T00 = new Date();
                SIPController.sipCall.invitingTimes++;
            }
        }
        return true;
    }

    public boolean sendRedirectCall(String message) {
        Log.e(TAG, "[sendRedirectCall] ===== START =====");
        if (cmcore.makeSendRedirectCall(SIPController.sipCall, message)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = new byte[SIPController.sipCall.message.length()];
                SIPController.sipCall.message.getBytes(0, SIPController.sipCall.message.length(), buffer, 0);

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
                SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_INVITING;
                SIPController.sipCall.callDirection = SIPStack.SIP_CALLDIRECTION_OUT;
                SIPController.sipCall.callTime_T0 = new Date();
                SIPController.sipCall.invitingTimes++;
                return true;
            }
        } else {
            SIPController.sipCall.resetCall();
        }
        return false;
    }

    public boolean reactionForWWWAUTHENTICATE(String message) {
        if (cmcore.makeReactionForWWWAUTHENTICATE(SIPController.sipCall, message)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length);
                        break;
                    }
                    repeatSendCount++;
                }

                SIPController.sipCall.callTime_T0 = new Date();
                SIPController.sipCall.callTime_T00 = new Date();
                return true;
            }
        }
        return false;
    }

    public boolean reactionForPROXYAUTHENTICATE(String message) {
        if (cmcore.makeReactionForPROXYAUTHENTICATE(SIPController.sipCall, message)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length);
                        break;
                    }
                    repeatSendCount++;
                }

                SIPController.sipCall.callTime_T0 = new Date();
                SIPController.sipCall.callTime_T00 = new Date();
                return true;
            }
        }
        return false;
    }

    public boolean sendProceeding(String remoteIp, int remotePort) {
        String sendmessage = cmcore.makeSendProceeding(SIPController.sipCall);

        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (sendmessage.length() > 0) {

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

                SIPController.sipCall.callTime_T6 = new Date();

                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
            }
        }
        return true;
    }

    //MultiCall Proceeding
    public boolean sendPendingProceeding(String remoteIp, int remotePort) {
        String sendmessage = cmcore.makeSendProceeding(SIPController.pendingCall);

        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (sendmessage.length() > 0) {

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//		        if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

                SIPController.pendingCall.callTime_T6 = new Date();
                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
            }
        }
        return true;
    }

    public boolean sendProgressing(String remoteIp, int remotePort) {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) return false;

        String sendmessage = cmcore.makeSendProgressing(SIPController.sipCall);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();
            if (sendmessage.length() > 0) {

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

                SIPController.sipCall.callTime_T6 = new Date();
                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
            }
        }
        return true;
    }

    //Multicall Progressing
    public boolean sendPendingProgressing(String remoteIp, int remotePort) {
        if (SIPController.pendingCall == null || SIPController.pendingCall.flag == false)
            return false;
        String sendmessage = cmcore.makeSendProgressing(SIPController.pendingCall);

        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();
            if (sendmessage.length() > 0) {

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

                SIPController.pendingCall.callTime_T6 = new Date();
                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
            }
        }
        return true;
    }

    public boolean sendProgressingwithbody(String remoteIp, int remotePort) {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) return false;
        if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
            String sendmessage = cmcore.makeSendProgressingwithbody(SIPController.sipCall);
            if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = sendmessage.getBytes();
                if (sendmessage.length() > 0) {

                    if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//				    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

                    SIPController.sipCall.callTime_T6 = new Date();
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }

                    if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                        if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                                SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);

                                if (SIPStack.bDirectCall) {
                                    // SERVICE MESSAGE NEEDED
                                    dialerVideoSet(true);
                                }
                            }
                        }
                    }
                }
            }
        }
        return true;
    }

    public boolean sendProgressingBlackcallwithbody(String remoteIp, int remotePort) {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) return false;
        if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
            String sendmessage = cmcore.makeSendProgressingwithbody(SIPController.sipCall);

            if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = sendmessage.getBytes();
                if (sendmessage.length() > 0) {

                    if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			        if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

                    SIPController.sipCall.callTime_T6 = new Date();
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }

                    if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                        if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                                SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);
                            }
                        }
                    }
                }
            }
        }
        return true;
    }

    public boolean acceptCancelRequest(String strMessage, String strRemoteIP, int strRemotePort) {
        try {
            LOG("[acceptCancelRequest] strMessage [" + strMessage + "], strRemoteIP [" + strRemoteIP + "], strRemotePort [" + strRemotePort + "]");
            String strSendMessage = cmcore.makeAcceptCancelRequest(SIPController.sipCall, strMessage);
            if (strSendMessage.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = strSendMessage.getBytes();
                if (strSendMessage.length() > 0) {
                    if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, strMessage);
//	                if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + strMessage);
                    SIPController.sipCall.callTime_T8 = new Date();
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(strRemoteIP, strRemotePort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }
                }
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "acceptCancelRequest(String strMessage, String strRemoteIP, int strRemotePort)");
            return false;
        }
    }

    public boolean acceptPendingCancelRequest(String message, String remoteIp, int remotePort) {
        String sendmessage = cmcore.makeAcceptCancelRequest(SIPController.pendingCall, message);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();
            if (sendmessage.length() > 0) {
                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//	            if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);
                SIPController.pendingCall.callTime_T8 = new Date();
                int repeatSendCount = 0;

                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
            }
            return true;
        }
        return false;
    }

    public boolean sendAccept() {
        String sendmessage = cmcore.makeSendAccept(SIPController.sipCall);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();
            if (sendmessage.length() > 0) {

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//		        if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

                SIPController.sipCall.callTime_T3 = new Date();
                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }

                SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_ACCEPTED;

                if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                    if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                        if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                            SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);
                            SIPController.audioRTPManager.RTPInit(SIPController.sipCall.sdp.audioM.mediaPort);

                            if (SIPStack.bDirectCall) {
                                // SERVICE MESSAGE NEEDED
                                dialerVideoSet(true);
                            }
                        }
                    }
                }
            }
            return true;
        } else return false;
    }

    public boolean directsendAccept() {
        try {
            LOG("[directsendAccept] ===== START =====");
            String sendmessage = cmcore.makeDirectsendAccept(SIPController.sipCall);
            if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = sendmessage.getBytes();
                if (sendmessage.length() > 0) {

                    if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//                    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

                    SIPController.sipCall.callTime_T3 = new Date();
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }

                    SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_ACCEPTED;

                    if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                        if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                                SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);
                                if (SIPController.audioRTPManager.rtpCore.bActive == false) {
                                    SIPController.audioRTPManager.RTPInit(SIPController.sipCall.sdp.audioM.mediaPort);
                                }

                                if (SIPStack.bDirectCall) {
                                    // SERVICE MESSAGE NEEDED
                                    dialerVideoSet(true);
                                }
                            }
                        }
                    }
                }
                return true;
            }
            return false;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] directsendAccept()");
            e.printStackTrace();
            return false;
        }
    }

    public boolean sendUpdateAccept() {
        String sendmessage = cmcore.makeSendUpdateAccept(SIPController.sipCall);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
            SIPController.sipCall.callTime_T6 = new Date();
            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }

            SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_UPDATEACCEPTED;

            if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                    if (SIPController.audioRTPManager != null) {
                        SIPController.audioRTPManager.setRemoteMediaInfo(SIPController.sipCall.remoteSdp.audioM.commonCodec, SIPController.sipCall.remoteSdp.audioM.mediaIp, SIPController.sipCall.remoteSdp.audioM.mediaPort);
                        if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager.rtpCore.bActive == false) {
                            SIPController.audioRTPManager.RTPInit(SIPController.sipCall.sdp.audioM.mediaPort);
                        }
                    }
                }
            }
            return true;
        }
        return false;
    }

    public boolean rejectCall(int code) {
        String sendmessage = cmcore.makeRejectCall(SIPController.sipCall, code);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//	        if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

            SIPController.sipCall.callTime_T6 = new Date();
            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }

            SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_TERMINATING;
            Log.i(TAG, "rejectCall code : " + code);
            // Phone status set
            // SERVICE MESSAGE NEEDED
            updateDialerStatus("Call reject.", true);
            return true;
        }
        return false;
    }

    public boolean redirectResponse(String contact) {
        String sendmessage = cmcore.makeRejectCall(SIPController.sipCall, 302, contact);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//		    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

            SIPController.sipCall.callTime_T6 = new Date();
            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }

            SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_TERMINATING;
            // Phone status set
            // SERVICE MESSAGE NEEDED
            updateDialerStatus("Call reject.", true);
            return true;
        }
        return false;
    }

    public boolean rejectPendingCall(int code) {
        Log.i("SIPStun", ">>>rejectPendingCall debug 1 " + SIPController.pendingCall.remoteIp + "  port:" + SIPController.pendingCall.remotePort);
        String sendmessage = cmcore.makeRejectCall(SIPController.pendingCall, code);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
            SIPController.pendingCall.callTime_T6 = new Date();
            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.pendingCall.remoteIp, SIPController.pendingCall.remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }
            //

            SIPController.pendingCall.callState = SIPStack.SIP_CALLSTATE_TERMINATING;

        }
        return true;
    }

    public boolean rejectCall(String message, int code, String remoteIp, int remotePort) {
        String sendmessage = cmcore.makeRejectCall(message, code, cmcore.localIp, cmcore.localPort, remoteIp, remotePort);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }
        }
        return true;
    }

    public boolean redirectIncomingCall(String redirectId) {
        String sendmessage = cmcore.makeRedirectIncomingCall(SIPController.sipCall, redirectId);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            // Phone status set
            // SERVICE MESSAGE NEEDED
            updateDialerStatus("Call forwarding to " + redirectId, true);
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

            SIPController.sipCall.callTime_T6 = new Date();
            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }
            SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_TERMINATING;
            return true;
        }
        return false;
    }

    public boolean sendProgressing(String body, String remoteIp, int remotePort) {
        String sendmessage = cmcore.makeSendProgressing(SIPController.sipCall, body);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

            SIPController.sipCall.callTime_T6 = new Date();
            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }
        }
        return true;
    }

    public boolean sendAck(String message) {
        if (cmcore.makeSendAck(SIPController.sipCall, message)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//	            if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                SIPController.sipCall.callTime_T4 = new Date();
                SIPController.sipCall.callTime_T40 = new Date();
                if (SIPController.sipCall.routeIp != null && SIPController.sipCall.routeIp.length() > 0 && SIPController.sipCall.routePort > 0) {
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.routeIp, SIPController.sipCall.routePort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }
                } else {
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }
                }
                return true;
            }
        }
        return false;
    }

    public boolean sendFinalAck(String message) {
        if (cmcore.makeSendFinalAck(SIPController.sipCall, message)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//	            if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                if (SIPController.sipCall.routeIp != null && SIPController.sipCall.routeIp.length() > 0 && SIPController.sipCall.routePort > 0) {
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.routeIp, SIPController.sipCall.routePort, buffer, buffer.length)) {
                            mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.routeIp, SIPController.sipCall.routePort, buffer, buffer.length);
                            mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.routeIp, SIPController.sipCall.routePort, buffer, buffer.length);
                            break;
                        }
                        repeatSendCount++;
                    }
                } else {
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                            mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length);
                            mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length);
                            break;
                        }
                        repeatSendCount++;
                    }
                }
                return true;
            }
        }
        return false;
    }

    public boolean sendFinalAck(String message, String remoteIp, int remotePort) {
        String sendmessage = cmcore.makeSendFinalAck(SIPController.sipCall, message, remoteIp, remotePort);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//		    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + sendmessage);

            if (remoteIp != null && remoteIp.length() > 0 && remotePort > 0) {
                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                        mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length);
                        mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length);
                        break;
                    }
                }
                return true;
            }
        }
        return false;
    }

    public boolean sendRedirectFinalAck(String message) {
        if (cmcore.makeSendRedirectFinalAck(SIPController.sipCall, message)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                if (SIPController.sipCall.routeIp != null && SIPController.sipCall.routeIp.length() > 0 && SIPController.sipCall.routePort > 0) {
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.routeIp, SIPController.sipCall.routePort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }
                } else {
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                            break;
                        }
                        repeatSendCount++;
                    }
                }
                return true;
            }
        }
        return false;
    }

    // REJECT OR BYE OR CANCEL
    public boolean callTerminate() {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) {
            return false;
        }

        SIPController.sipCall.bCancelRequest = false;

        if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CONNECTED || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_ACCEPTED || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_REMOTEACCEPTED) {
            // Phone status set
            // SERVICE MESSAGE NEEDED
            updateDialerStatus("Call disconnecting.", false);

            int duration = 0;
            Date currentTime = new Date();
            if (SIPController.sipCall.callTime_T4 != null) {
                duration = (int) (currentTime.getTime() - SIPController.sipCall.callTime_T4.getTime()) / 1000;
                if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN)
                    duration -= 1;
                if (duration < 0) duration = 0;
            }

            Log.e(TAG, "[JEFF] ========== RTP END 4 ==========");
            if (SIPController.audioRTPManager != null) SIPController.audioRTPManager.RTPEnd();
            if (SIPStack.bDirectCall) {
                // SERVICE MESSAGE NEEDED
                dialerVideoSet(false);
            }
            return sendBye();
        } else if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_INVITING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROCEEDING || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_PROGRESSING) {
            // Phone status set
            // SERVICE MESSAGE NEEDED
            updateDialerStatus("Call cancelling.", false);

            Log.e(TAG, "[JEFF] ========== RTP END 5 ==========");
            if (SIPController.audioRTPManager != null) SIPController.audioRTPManager.RTPEnd();
            if (SIPStack.bDirectCall) {
                // SERVICE MESSAGE NEEDED
                dialerVideoSet(false);
            }
            return sendCancel();
        } else if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED || SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CANCELLED)) {
            // Phone status set
            // SERVICE MESSAGE NEEDED
            updateDialerStatus("Call reject.", false);
            return rejectCall(480);
        } else if (SIPController.sipCall.flag && SIPController.sipCall.callState != SIPStack.SIP_CALLSTATE_TERMINATING) {
            Log.e(TAG, "[JEFF] ========== RTP END 6 ==========");
            if (SIPController.audioRTPManager != null) SIPController.audioRTPManager.RTPEnd();
            if (SIPStack.bDirectCall) {
                // SERVICE MESSAGE NEEDED
                dialerVideoSet(false);
            }
            // SERVICE MESSAGE NEEDED
            dialerNotifyCallEnd("", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
            SIPController.sipCall.resetCall();
//			return sendCancel();   // JEFF (2015.10.21)
        } else {
            Log.e(TAG, "[callTerminate] ===== NO IF =====");
        }
        return true;
    }

    // Redirect response
    public boolean redirectTerminate(String contact) {
        LOG_INFO("[redirectTerminate] ===== START =====");
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) {
            return false;
        }

        LOG_INFO("[redirectTerminate] contact [" + contact + "]");
        SIPController.sipCall.bForwardRequest = false;

        if (SIPController.sipCall.callDirection == SIPStack.SIP_CALLDIRECTION_IN && (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED)) {
            // Phone status set
            // SERVICE MESSAGE NEEDED
            LOG_INFO("[redirectTerminate] ===== JEFF 4 START =====");
            LOG_INFO("[redirectTerminate] BSSVideo.HNS_SERVICE_RECEIVER_SELECTED [" + BSSVideo.HNS_SERVICE_RECEIVER_SELECTED + "]");
            LOG_INFO("[redirectTerminate] SIPController.sipCall.remoteIp : " + SIPController.sipCall.remoteIp);
            LOG_INFO("[redirectTerminate] SIPController.sipCall.number : " + SIPController.sipCall.number);
            LOG_INFO("[redirectTerminate] SIPController.sipCall.cid : " + SIPController.sipCall.cid);
            LOG_INFO("[redirectTerminate] SIPController.sipCall.dnis : " + SIPController.sipCall.dnis);
            LOG_INFO("[redirectTerminate] SIPController.sipCall.dong_number : " + SIPController.sipCall.dong_number);
            LOG_INFO("[redirectTerminate] SIPController.sipCall.ho_number : " + SIPController.sipCall.ho_number);
            LOG_INFO("[redirectTerminate] SIPController.sipCall.id : " + SIPController.sipCall.id);
            LOG_INFO("[redirectTerminate] ===== JEFF 4 END =====");
            updateDialerStatus("Call forwarded.", false);
            return redirectResponse(contact);
        } else if (SIPController.sipCall.flag && SIPController.sipCall.callState != SIPStack.SIP_CALLSTATE_TERMINATING) {
            Log.e(TAG, "[JEFF] ========== RTP END 13 ==========");
            if (SIPController.audioRTPManager != null) SIPController.audioRTPManager.RTPEnd();
            if (SIPStack.bDirectCall) {
                // SERVICE MESSAGE NEEDED
                dialerVideoSet(false);
            }
            // SERVICE MESSAGE NEEDED
            dialerNotifyCallEnd("", SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort, false);
            SIPController.sipCall.resetCall();
        }
        return true;
    }

    // BYE
    public boolean sendBye() {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) return false;
        if (cmcore.makeBye(SIPController.sipCall)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();
                if (SIPController.sipCall.message.length() > 0) {

                    if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				    if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                    SIPController.sipCall.callTime_T5 = new Date();
                    SIPController.sipCall.callTime_T6 = new Date();
                    SIPController.sipCall.callTime_T9 = new Date();
                    SIPController.sipCall.bByedisconnected = true;
                    SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_DISCONNECTING;
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                            mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length);
                            mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length);
                            break;
                        }
                        repeatSendCount++;
                    }
                }
            }
            return true;
        }
        return false;
    }

    public boolean resendBye() {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) return false;
        if (SIPController.sipCall.callState != SIPStack.SIP_CALLSTATE_DISCONNECTING) return false;
        if (cmcore.makeReBye(SIPController.sipCall)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();
                if (SIPController.sipCall.message.length() > 0) {

                    if (bPrintSIPMsg)
                        printSIPMessage(MESSAGE.RESEND, SIPController.sipCall.message);

                    SIPController.sipCall.callTime_T9 = new Date();
                    SIPController.sipCall.bByedisconnected = true;
                    int repeatSendCount = 0;
                    while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                        if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                            mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length);
                            mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length);
                            break;
                        }
                        repeatSendCount++;
                    }
                }
            }
            return true;
        }
        return false;
    }

    public boolean sendByeResponse(String message, String remoteIp, int remotePort) {
        String sendmessage = cmcore.makeSendByeResponse(SIPController.sipCall, message);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

            SIPController.sipCall.callTime_T6 = new Date();
            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                    mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length);
                    mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length);
                    break;
                }
                repeatSendCount++;
            }
        }
        return true;
    }

    // CANCEL
    public boolean sendCancel() {
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) return false;
        if (cmcore.makeCancel(SIPController.sipCall)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                SIPController.sipCall.callTime_T8 = new Date();
                SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_CANCELLING;
                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
                return true;
            }
        }
        return false;
    }

    public boolean sendRecancel() {
        //Log.i(TAG, "RECANCELLING");
        if (SIPController.sipCall == null || SIPController.sipCall.flag == false) return false;
        if (cmcore.makeRecancel(SIPController.sipCall)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                SIPController.sipCall.callTime_T8 = new Date();
                SIPController.sipCall.callState = SIPStack.SIP_CALLSTATE_RECANCELLING;
                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
                return true;
            }
        }
        return false;
    }

    // OPTIONS
    public boolean sendOptionsResponse(String message, String remoteIp, int remotePort, int code) {
        String sendmessage = cmcore.makeSendOptionsResponse(SIPController.sipCall, message, code);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }
            return true;
        }
        return false;
    }

    //INFO
    public boolean sendInfoResponse(String message, String remoteIp, int remotePort, int code) {
        String sendmessage = cmcore.makeSendInfoResponse(SIPController.sipCall, message, code);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }
        } else return false;

        // DTMF PARSE
        SIPHeader sipHeader = new SIPHeader(message, SIPStack.SIP_HEADERTYPE_CONTENTTYPE);
        if (sipHeader != null && sipHeader.flag && sipHeader.headerValue != null && sipHeader.headerValue.length() > 0) {
            if (sipHeader.headerValue.compareTo("application/dtmf-relay") == 0) {
                // DTMF-RELAY TYPE
                if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.parseDtmfSdp(message, SIPStack.SIP_DTMFINFO_DTMFRELAY)) {
                    // SERVICE MESSAGE NEEDED
                    dialerNotifyDtmf(SIPController.sipCall.detectedDtmf);
                }
            } else if (sipHeader.headerValue.compareTo("application/dtmf") == 0) {
                // DTMF TYPE
                if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.parseDtmfSdp(message, SIPStack.SIP_DTMFINFO_DTMF)) {
                    // SERVICE MESSAGE NEEDED
                    dialerNotifyDtmf(SIPController.sipCall.detectedDtmf);
                }
            }
        }
        return true;
    }

    // OPTIONS
    public boolean sendMessageResponse(String message, String remoteIp, int remotePort, int code) {
        String sendmessage = cmcore.makeSendInfoResponse(SIPController.sipCall, message, code);
        if (sendmessage.length() > 0 && mSIPSignalReceiver != null) {
            byte[] buffer = sendmessage.getBytes();

            if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, sendmessage);
//			if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SENT\n" + sendmessage);

            int repeatSendCount = 0;
            while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(remoteIp, remotePort, buffer, buffer.length)) {
                    break;
                }
                repeatSendCount++;
            }
            return true;
        }
        return false;
    }

    public boolean sendUpdate() {
        if (cmcore.makeSendUpdate(SIPController.sipCall)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
                SIPController.sipCall.callTime_T0 = new Date();
                return true;
            }
        }
        return false;
    }

    public boolean sendUpdate(String flow) {
        if (cmcore.makeSendUpdate(SIPController.sipCall, flow)) {
            if (SIPController.sipCall.message.length() > 0 && mSIPSignalReceiver != null) {
                byte[] buffer = SIPController.sipCall.message.getBytes();

                if (bPrintSIPMsg) printSIPMessage(MESSAGE.SEND, SIPController.sipCall.message);
//				if (SIPStack.SIP_MESSAGE_DEBUG) Log.i(TAG, "SEND\n" + SIPController.sipCall.message);

                int repeatSendCount = 0;
                while (repeatSendCount < SIPStack.REPEAT_SENDCOUNT) {
                    if (buffer.length == mSIPSignalReceiver.BSSSipSendUdpPacket(SIPController.sipCall.remoteIp, SIPController.sipCall.remotePort, buffer, buffer.length)) {
                        break;
                    }
                    repeatSendCount++;
                }
                SIPController.sipCall.callTime_T0 = new Date();
                return true;
            }
        }
        return false;
    }

    public void sendHold() {
        if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.callMode == SIPStack.SIP_CALLMODE_BASIC && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CONNECTED) {
            if (SIPController.sipCall.bHolding) {
                SIPController.sipCall.bHolding = false;
                sendUpdate("sendrecv");
                if (SIPController.sipSound != null)
                    SIPController.sipSound.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDRECV;
            } else {
                SIPController.sipCall.bHolding = true;
                sendUpdate();
                if (SIPController.sipSound != null)
                    SIPController.sipSound.flowIndicator = SIPStack.SIP_MEDIAFLOW_SENDONLY;
            }
        }
    }

    public void updateDialerStatus(String arg1, boolean bSet) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("UPDATESTATUS", arg1);
                Message msg = null;
                if (bSet)
                    msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_UPDATESTATUS_TRUE);
                else msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_UPDATESTATUS_FALSE);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] updateDialerStatus(String arg1, boolean bSet)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] updateDialerStatus(String arg1, boolean bSet)");
                e.printStackTrace();
            }
        }
    }

    public void dialerVideoSet(boolean bSet) {
//        for (int i = mClients.size() - 1; i >= 0; i--) {
//            try {
//                // Send data as a String
//                Bundle b = new Bundle();
//                b.putString("VIDEOSET", "null");
//                Message msg = null;
//                if (bSet)
//                    msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_VIDEOSET_TRUE);
//                else msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_VIDEOSET_FALSE);
//                msg.setData(b);
//                mClients.get(i).send(msg);
//            } catch (RemoteException e) {
//                Log.e(TAG, "[RemoteException] dialerVideoSet(boolean bSet)");
//                e.printStackTrace();
//                mClients.remove(i);
//            } catch (Exception e) {
//                Log.e(TAG, "[Exception] dialerVideoSet(boolean bSet)");
//                e.printStackTrace();
//            }
//        }
    }



    public void dialerNotifyIncomingCall(String dn, String uri) {
        //Log.i(TAG,"dialerNotifyIncomingCall invoked");
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("INCOMINGCALL", dn + ";" + uri);
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_INCOMINGCALL);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyIncomingCall(String dn, String uri)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyIncomingCall(String dn, String uri)");
                e.printStackTrace();
            }
        }
    }

    public void dialerNotifyIncomingMultiCall(String dn, String uri) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("INCOMINGMULTICALL", dn + ";" + uri);
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_INCOMINGMULTICALL);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyIncomingMultiCall(String dn,String uri)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyIncomingMultiCall(String dn,String uri)");
                e.printStackTrace();
            }
        }
    }

    public void dialerNotifyCallConnected(String dn, String uri) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("CALLCONNECTED", dn + ";" + uri);
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_CALLCONNECTED);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyCallConnected(String dn, String uri)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyCallConnected(String dn, String uri)");
                e.printStackTrace();
            }
        }
    }

    public void dialerNotifyBackgroundIncomingCall(String dn, String uri) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("BACKGROUNDINCOMINGCALL", dn + ";" + uri);
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_BACKGROUNDINCOMINGCALL);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyBackgroundIncomingCall(String dn, String uri)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyBackgroundIncomingCall(String dn, String uri)");
                e.printStackTrace();
            }
        }
    }

    // shutdownApplication()
    public void dialerShutdownApplication() {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("SHUTDOWNAPPLICATION", "");
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_SHUTDOWNAPPLICATION);
                msg.setData(b);
                mClients.get(i).send(msg);

            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerShutdownApplication()");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerShutdownApplication()");
                e.printStackTrace();
            }
        }
    }

    // vibrator(boolean bSet)
    public void dialerVibrator(boolean bSet) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("VIBRATOR", "null");
                Message msg = null;
                if (bSet)
                    msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_VIBRATOR_TRUE);
                else msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_VIBRATOR_FALSE);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerVibrator(boolean bSet)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerVibrator(boolean bSet)");
                e.printStackTrace();
            }
        }


    }

    // registerStatus(SIPStack.bNetworkActive);
    public void dialerRegistStatus(boolean bSet) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("REGISTSTATUS", "null");
                Message msg = null;
                if (bSet)
                    msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_REGISTSTATUS_TRUE);
                else msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_REGISTSTATUS_FALSE);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerRegistStatus(boolean bSet)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerRegistStatus(boolean bSet)");
                e.printStackTrace();
            }
        }
    }

    // notifyRingbackTone(false)
    public void dialerNotifyRingbackTone(boolean bSet) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("RINGBACKTONE", "null");
                Message msg = null;
                if (bSet)
                    msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_RINGBACKTONE_TRUE);
                else msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_RINGBACKTONE_FALSE);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyRingbackTone(boolean bSet)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyRingbackTone(boolean bSet)");
                e.printStackTrace();
            }
        }
    }

    // notifyCallEnd(value, false);
    public void dialerNotifyCallEnd(String status, String dn, String uri, boolean bSet) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("CALLEND", status + ";" + dn + ";" + uri);
                Message msg = null;
                if (bSet)
                    msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_CALLEND_TRUE);
                else msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_CALLEND_FALSE);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyCallEnd(String status, String dn, String uri, boolean bSet)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyCallEnd(String status, String dn, String uri, boolean bSet)");
                e.printStackTrace();
            }
        }

        if (SIPStun.bBlackCall) {
            SIPStun.bBlackCall = false;
            if (SIPStun.bBlackCallSupport) SIPStack.bShutdownApplication = true;
        }
    }

    // dialerNotifyCallFail(SIPController.sipCall.responseCode,SIPController.sipCall.remoteIp);
    public void dialerNotifyCallFail(int finalCode, String remoteip) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("CALLFAIL", finalCode + "|" + remoteip);
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_OUTCALLFAIL);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyCallFail(int finalCode, String remoteip)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyCallFail(int finalCode, String remoteip)");
                e.printStackTrace();
            }
        }
    }

    //notifyDtmf(SIPController.sipCall.detectedDtmf);
    public void dialerNotifyDtmf(int dtmf) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("OUTBANDDTMF", dtmf + "");
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_OUTBANDDTMF);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyDtmf(int dtmf)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyDtmf(int dtmf)");
                e.printStackTrace();
            }
        }
    }

    public void dialerPadNumber(String number) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("PADNUMBER", number);
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_PADNUMBER);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerPadNumber(String number)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerPadNumber(String number)");
                e.printStackTrace();
            }
        }
    }

    public void dialerPadType(int padType, int officeNumber) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                String value = padType + "." + officeNumber;
                b.putString("PADTYPE", value);
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_PADTYPE);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerPadType(int padType, int officeNumber)");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerPadType(int padType, int officeNumber)");
                e.printStackTrace();
            }
        }
    }

    // BSSSIPStun_ICONTROLS_CM_CANCELMULTICALL
    public void dialerNotifyMulticallCancel() {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            try {
                // Send data as a String
                Bundle b = new Bundle();
                b.putString("CANCELMULTICALL", "");
                Message msg = null;
                msg = Message.obtain(null, CMCore.BSSSIPStun_ICONTROLS_CM_CANCELMULTICALL);
                msg.setData(b);
                mClients.get(i).send(msg);
            } catch (RemoteException e) {
                Log.e(TAG, "[RemoteException] dialerNotifyMulticallCancel()");
                e.printStackTrace();
                mClients.remove(i);
            } catch (Exception e) {
                Log.e(TAG, "[Exception] dialerNotifyMulticallCancel()");
                e.printStackTrace();
            }
        }
    }

    private void printSIPMessage(MESSAGE eType, String strMessage) {
        try {
            Log.w(TAG, "[printSIPMessage] ========== eType [" + eType + "] ==========");
            Log.d(TAG, strMessage);
            Log.w(TAG, "========== End of SIP message ==========");
        } catch (Exception e) {
            Log.e(TAG, "[Exception] printSIPMessage(MESSAGE eType, String strMessage)");
            e.printStackTrace();
        }
    }

    enum MESSAGE {
        SEND,   // 전송
        RESEND,   // 재전송
        RECEIVE,   // 수신
    }

    class CmPiper extends Handler { // Handler of incoming messages from UI.

        @Override
        public void handleMessage(Message msg) {
            String value = "null";
            switch (msg.what) {
                case CMCore.BSSSIPStun_ICONTROLS_REGISTER:
                    mClients.add(msg.replyTo);
                    Log.i(TAG, "SIPStun CmPiper DIALER_REGISTER : " + msg.toString());
                    if (SIPStack.bDirectCall) {
                        if (padNumber == null || padNumber.length() == 0) {
                            boolean bValidroom = getMyroomname();
                            if (bValidroom == false) {
                                Log.i(TAG, "Invalid room");
                                dialerPadNumber("");
                            } else dialerPadNumber(padNumber);
                        } else dialerPadNumber(padNumber);

                        if (SIPStun.bBlackCallBackgroundMode) {
                            if (SIPStun.bBlackCall && SIPController.sipCall.flag && SIPController.sipCall.bResponsebackgroundcall && SIPController.sipCall.bResponsebackgroundcallReady == false) {
                                SIPController.sipCall.bResponsebackgroundcallReady = true;
                                SIPController.sipCall.responsebackgroundcallTimer = new Date();
                            } else {
                                dialerPadType(BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED, officeNumber);
                            }
                        } else {
                            dialerPadType(BSSVideo.HNS_SERVICE_ORIGINATOR_SELECTED, officeNumber);
                        }
                    }
                    break;

                case CMCore.BSSSIPStun_ICONTROLS_UNREGISTER:
                    mClients.remove(msg.replyTo);
                    Log.i(TAG, "SIPStun CmPiper CMCore.BSSSIPStun_ICONTROLS_UNREGISTER : " + msg.toString());
                    break;

                case CMCore.BSSSIPStun_ICONTROLS_DIALER_COMMAND:
                    Log.i(TAG, "SIPStun CmPiper CMCore.BSSSIPStun_ICONTROLS_DIALER_COMMAND : " + msg.toString());
                    break;

                case CMCore.BSSSIPStun_ICONTROLS_CONTACT_CALLNEIGHBOR:
                    value = msg.getData().getString("CALLNEIGHBOR");
                    Log.i(TAG, ">>>SIPStun CmPiper BSSSIPStun_ICONTROLS_CONTACT_CALLNEIGHBOR : " + value);
                    if (CMCore.bDialerActive == false) {
                        Context context = SIPStun.this;   // Contexts.SERVICE;
                        Intent intent = new Intent(context, V40IFCCD.class);
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        context.startActivity(intent);
                    }
                    break;

                case CMCore.BSSSIPStun_ICONTROLS_CONTACT_CALLGUARD:
                    value = msg.getData().getString("CALLGUARD");
                    Log.i(TAG, ">>>SIPStun CmPiper BSSSIPStun_ICONTROLS_CONTACT_CALLGUARD : " + value);
                    break;

                case CMCore.BSSSIPStun_ICONTROLS_DIALER_ACCEPTMULTICALL:
                    value = msg.getData().getString("ACCEPTMULTICALL");
                    if (SIPController.pendingCall != null && SIPController.pendingCall.flag) {
                        SIPController.pendingCall.bAsMaster = true;
                    }
                    Log.i(TAG, ">>>SIPStun CmPiper BSSSIPStun_ICONTROLS_DIALER_ACCEPTMULTICALL");
                    break;

                case CMCore.BSSSIPStun_ICONTROLS_DIALER_REJECTMULTICALL:
                    value = msg.getData().getString("REJECTMULTICALL");
                    if (SIPController.pendingCall != null && SIPController.pendingCall.flag) {
                        SIPController.pendingCall.bRejectRequest = true;
                    }
                    Log.i(TAG, ">>>SIPStun CmPiper BSSSIPStun_ICONTROLS_DIALER_REJECTMULTICALL");
                    break;

                case CMCore.BSSSIPStun_ICONTROLS_DIALER_FORWARD:
                    value = msg.getData().getString("FORWARD");
                    if (SIPController.sipCall != null && SIPController.sipCall.flag) {
                        Log.i(TAG, ">>>SIPStun CmPiper BSSSIPStun_ICONTROLS_DIALER_FORWARD : " + value);
                        SIPController.forward.contact = new String(value);
                        SIPController.sipCall.bForwardRequest = true;
                    }
                    Log.i(TAG, ">>>SIPStun CmPiper BSSSIPStun_ICONTROLS_DIALER_FORWARD");
                    Log.d(TAG, "FORWARD : " + value);
                    break;

                default:
                    Log.i(TAG, "SIPStun CmPiper default:" + msg.toString());
                    super.handleMessage(msg);
            }
        }
    }

    // SignalReceiver
    class SIPSignalReceiver extends Thread {
        protected DatagramSocket theSocket;
        protected DatagramPacket dp;
        protected boolean bFlag = false;
        InetAddress thisComputer;
        boolean bReady = false;
        byte[] buffer;

        public SIPSignalReceiver(InetAddress thisComputer, int port) {
            bReady = false;
            try {
                if (port > 0 && port <= 65556) {
                    SIPStack.SIP_SIGNAL_PORT = port;
                    for (int i = 0; i < SIPStack.MAX_SIGNAL_PORTS; i++) {
                        SIPStack.SIP_SIGNAL_PORT = port + i;
                        Log.i(TAG, "try SIP Signal socket create  on " + SIPStack.SIP_SIGNAL_PORT);
                        try {
                            theSocket = new DatagramSocket(SIPStack.SIP_SIGNAL_PORT);
                        } catch (Exception e) {
                            Log.e(TAG, "[Exception] SipSignalReceiver -> SipSignalReceiver (InetAddress thisComputer, int port)");
                        }
                        if (theSocket != null) {
                            bFlag = true;
                            break;
                        }
                    }

                    if (theSocket == null) {
                        Log.i(TAG, "[SipSignalReceiver] theSocket is null!!!");
                        bFlag = false;
                        return;
                    }

                    theSocket.setReuseAddress(true);
                    this.thisComputer = thisComputer;
                }

                buffer = new byte[SIPStack.SIP_MAXMESSAGE_SIZE];

            } catch (SocketException se) {
                Log.e(TAG, "[SocketException] ERROR SipSignalReceiver Construct");
                System.err.println(se);
                SIPStack.exceptionCountAtCurrentCall++;
            } catch (Exception e) {
                Log.e(TAG, "[Exception] SipSignalReceiver construct exception occurred.");
            }
        }//SipSignalReceiver()

        public void run() {
            Log.i(TAG, "[SipSignalReceiver] run() >>>> Signal Thread receive ready.");
            try {
                dp = new DatagramPacket(buffer, buffer.length);
            } catch (NullPointerException ne) {
                System.err.println(ne);
                SIPStack.exceptionCountAtCurrentCall++;
                return;
            }

            bReady = true;
            this.setPriority(1);

            while (bReady && theSocket != null && dp != null) {
                try {
                    Log.i(TAG, "[SipSignalReceiver] >>>>  SOCKET SoTimeout : " + theSocket.getSoTimeout());
                    dp.setLength(SIPStack.SIP_MAXMESSAGE_SIZE);
                    dp.setData(buffer);
                    theSocket.receive(dp);
                    if (CMCore.bPausing) {
                        Date currentTime = new Date();
                        int milli = (int) (currentTime.getTime() - CMCore.pauseTime.getTime());
                        if (milli < CMCore.BSSSIPStun_ICONTROLS_PAUSING_DURATION) {
                            Log.e(TAG, "===== CMCore.bPausing [" + CMCore.bPausing + "], pause duration [" + milli + "]. signal is ignored!!! (PASS BY JEFF, 2015.09.07) =====");
                            continue;
                        }
                    }

                    if (0 != BSSSipParser(dp)) {
                        if (SIPStack.SIP_MESSAGE_DEBUG)
                            Log.i(TAG, "SIP MESSAGE PARSER ERROR");
                        Thread.yield();
                    }
                    SIPStack.bIntraffic = true;
                } catch (SocketTimeoutException se) {
                    Log.e(TAG, "[SocketTimeoutException] Socket time out...");
                    se.printStackTrace();
                } catch (IOException e) {
                    Log.e(TAG, "[IOException] IOException");
                    e.printStackTrace();
                    System.err.println(e);
                    SIPStack.exceptionCountAtCurrentCall++;
                } catch (Exception e1) {
                    Log.e(TAG, "[Exception] +++ SipSignalReceiver receive thread exception occurred.");
                    e1.printStackTrace();
                    System.err.println(e1);
                    e1.printStackTrace();
                }
            }   // while
            Log.e(TAG, "========== Signal Thread terminated ==========");
        }

        public int BSSSipParser(DatagramPacket dp) {
            if (dp == null) return -1;

            String remoteIp = null;
            byte[] address = dp.getAddress().getAddress();
            if (address == null || address.length <= 0) return -1;
            if (address.length == 4) {
                int unsignedByte1 = address[0] < 0 ? address[0] + 256 : address[0];
                int unsignedByte2 = address[1] < 0 ? address[1] + 256 : address[1];
                int unsignedByte3 = address[2] < 0 ? address[2] + 256 : address[2];
                int unsignedByte4 = address[3] < 0 ? address[3] + 256 : address[3];
                remoteIp = unsignedByte1 + "." + unsignedByte2 + "." + unsignedByte3 + "." + unsignedByte4;
            } else return -1;

            int remotePort = dp.getPort();
            if (remotePort <= 0) return -1;
            int iMessageType = 0;   // 0:not defined 1:request 2:response
            int iMethodType = 0; //
            String s = new String(dp.getData(), 0, 0, dp.getLength());
            if (s == null || s.length() <= 0) return -1;

            // SIP PARSE
            StringTokenizer st = new StringTokenizer(s, "\n", true);
            if (st.hasMoreTokens()) {
                String str = st.nextToken();
                if (str.length() > 0) {
                    iMethodType = SIPStack.getRequestlineMethod(str);
                    if (iMethodType == SIPStack.SIP_METHODTYPE_NONE) {
                        return 0;
                    } else if (iMethodType == SIPStack.SIP_METHODTYPE_RESPONSE) {
                        iMethodType = SIPStack.getCSeqMethod(s);
                        if (iMethodType == SIPStack.SIP_METHODTYPE_NONE) return 0;

                        iMessageType = SIPStack.SIP_MSGTYPE_RESPONSE;

                        if (iMethodType == SIPStack.SIP_METHODTYPE_REGISTER)
                            SIPParser(s, iMessageType, iMethodType);
                        else if (iMethodType != SIPStack.SIP_METHODTYPE_NONE)
                            SIPParser(s, iMessageType, iMethodType, remoteIp, remotePort);

                        return 0;
                    } else {
                        iMessageType = SIPStack.SIP_MSGTYPE_REQUEST;
                        SIPParser(s, iMessageType, iMethodType, remoteIp, remotePort);
                    }
                }
            }
            return 0;
        }

        public int BSSSipSendUdpPacket(String sIp, int iPort, byte[] data, int dataSize) {
            int sent = 0;
            if (sIp == null || sIp.length() == 0) return 0;
            if (iPort <= 0) return 0;
            if (dataSize <= 0) return 0;

            try {
                InetAddress ia = InetAddress.getByName(sIp);

                if (ia != null) {
                    DatagramPacket dp = new DatagramPacket(data, dataSize, ia, iPort);
                    if (dp != null) theSocket.send(dp);

                    sent = dataSize;
                    SIPStack.bOuttraffic = true;

                    if (bPrintSIPMsgIO) printSIPMessage(MESSAGE.SEND, new String(data));
                }
            } catch (UnknownHostException uhe) {
                Log.e(TAG, "[UnknownHostException] BSSSipSendUdpPacket(String sIp, int iPort, byte[] data, int dataSize)");
                System.err.println(uhe);
                SIPStack.exceptionCountAtCurrentCall++;
            } catch (java.net.SocketException she) {
                Log.e(TAG, "[SocketException] Cause:  " + she.getCause());
                Log.e(TAG, "[SocketException] Reason: " + she.getMessage());

                if (she.getMessage().indexOf("ENETUNREACH") >= 0 || she.getMessage().indexOf("Network is unreachable") >= 0) {
                    SIPStack.networkStatus = SIPStack.SIP_NETIF_UNREACHABLE;
                    Log.e(TAG, "[BSSSipSendUdpPacket] networkStatus was set to SIP_NETIF_UNREACHABLE");
                }

                System.err.println(she);

                try {
                    Log.e(TAG, "!!! Socket is invalid, renew.");
                    theSocket = new DatagramSocket(SIPStack.SIP_SIGNAL_PORT);
                } catch (Exception e) {
                    Log.e(TAG, "[Exception] !!! Socket is invalid, renew.");
                }
                SIPStack.exceptionCountAtCurrentCall++;
            } catch (IOException ie) {
                Log.e(TAG, "[IOException] BSSSipSendUdpPacket(String sIp, int iPort, byte[] data, int dataSize)");
                System.err.println(ie);
                SIPStack.exceptionCountAtCurrentCall++;
            } catch (Exception e) {
                Log.e(TAG, "[Exception] BSSSipSendUdpPacket(String sIp, int iPort, byte[] data, int dataSize)");
                Log.e(TAG, "!!!BSSSipSendUdpPacket Exception occurred. <BSS> : " + sent);
                System.err.println(e);
                return -1;
            }
            return sent;
        }
    }//class SipSignalReceiver

    class SIGNALCTRLThread extends Thread {
        @Override
        public void run() {
            while (cmcore.SIGNALCTRLRunning) {
//    	        Log.w(TAG, "[SIGNALCTRLThread]");
                try {
                    Thread.sleep(SIPStack.SIPCTRL_INTERVAL);
                    if (cmcore.SIGNALCTRLThread == null) {
//  	    		      Log.e(TAG, "[SIGNALCTRLThread] ========== 1 ==========");
                        break;
                    }

                    if (cmcore.SIGNALCTRLThread.isInterrupted()) {
//  	    			  Log.e(TAG, "[SIGNALCTRLThread] ========== 2 ==========");
                        break;
                    }

                    if (SIPStack.networkStatus != SIPStack.SIP_NETIF_AVAILABLE) {
//  	  	 			Log.e(TAG, "[SIGNALCTRLThread] ========== 3 ==========");
                        if (SIPStack.networkStatus == SIPStack.SIP_NETIF_UNREACHABLE) {
//  	  	 			   Log.e(TAG, "[SIGNALCTRLThread] ========== 4 ==========");
                            // SERVICE MESSAGE NEEDED
                            updateDialerStatus("NETWORK UNREACHABLE.", true);
                        } else if (SIPStack.networkStatus == SIPStack.SIP_NETIF_UNAVAILABLE) {
//  	  	 				Log.e(TAG, "[SIGNALCTRLThread] ========== 5 ==========");
                            // SERVICE MESSAGE NEEDED
                            updateDialerStatus("NETWORK not ready.", true);
                        }

                        if (SIPStack.networkStatus == SIPStack.SIP_NETIF_UNAVAILABLE || SIPStack.networkStatus == SIPStack.SIP_NETIF_UNREACHABLE) {
//  	  	 				Log.e(TAG, "[SIGNALCTRLThread] ========== 6 ==========");
                            if (connectivityManager != null && connectivityManager.getActiveNetworkInfo() != null) {
//  	  	 				   Log.e(TAG, "[SIGNALCTRLThread] ========== 7 ==========");
                                NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();

                                switch (activeNetwork.getType()) {

                                    case ConnectivityManager.TYPE_WIMAX: // 4g 망 체크
//  	  	 							Log.e(TAG, "[SIGNALCTRLThread] ========== 8 ==========");
                                        if (SIPStack.isInternetWiMax == false && SIPStack.bBackgroundRunning)
                                            SIPStack.bShutdownApplication = true;

                                        SIPStack.isInternetWiMax = true;
                                        SIPStack.isInternetWiFi = false;
                                        SIPStack.isInternetMobile = false;
                                        SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                                        break;

                                    case ConnectivityManager.TYPE_WIFI: // wifi망 체크
//  	  	 							Log.e(TAG, "[SIGNALCTRLThread] ========== 9 ==========");
                                        if (SIPStack.isInternetWiFi == false && SIPStack.bBackgroundRunning)
                                            SIPStack.bShutdownApplication = true;
                                        SIPStack.isInternetWiMax = false;
                                        SIPStack.isInternetWiFi = true;
                                        SIPStack.isInternetMobile = false;
                                        SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                                        break;

                                    case ConnectivityManager.TYPE_MOBILE: // 3g 망 체크
//  	  	 							Log.e(TAG, "[SIGNALCTRLThread] ========== 10 ==========");
                                        if (SIPStack.isInternetMobile == false && SIPStack.bBackgroundRunning)
                                            SIPStack.bShutdownApplication = true;
                                        SIPStack.isInternetWiMax = false;   //false;
                                        SIPStack.isInternetWiFi = false;
                                        SIPStack.isInternetMobile = true;
                                        SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                                        break;

                                }
                            }

                            cmcore.netcheckIntervalTimer = new Date();
                            try {
//  	  	 					Log.e(TAG, "[SIGNALCTRLThread] ========== 11 ==========");
                                String host = SIPController.getSHVE140SLocalIpAddress();
                                cmcore.action_net_1(host);
                            } catch (Exception e) {
                                Log.e(TAG, "[Exception] String host = SIPController.getSHVE140SLocalIpAddress();");
                            }
                        }
                        continue;
                    }

                    if (SIPStack.bDirectCall == false && cmcore.regState != SIPStack.SIP_REGSTATE_REGISTERED) {
//  	  	 			Log.e(TAG, "[SIGNALCTRLThread] ========== 12 ==========");
                        if (cmcore.action_net_0()) sendRegister();
                    }

                    // REGIST CONTROL
                    if (cmcore.ctrlIndex == 0) {
//  	  	 			Log.e(TAG, "[SIGNALCTRLThread] ========== 13 ==========");
                        if (SIPStack.bShutdownApplication) {
//  	  	 			   Log.e(TAG, "[SIGNALCTRLThread] ========== 14 ==========");
                            if (SIPStack.bDirectCall == false) {
//  	  	 			       Log.e(TAG, "[SIGNALCTRLThread] ========== 15 ==========");
                                sendUNRegister();
                            }
                            SIPStack.bShutdownApplication = false;
                            // SERVICE MESSAGE NEEDED
                            dialerShutdownApplication();
                        }

                        if (SIPStack.bDirectCall == false) {
//  	  	 				Log.e(TAG, "[SIGNALCTRLThread] ========== 16 ==========");
                            SIPCTRLRegister();
                        }
                    } else if (cmcore.ctrlIndex == 1) {
//  	  	 			Log.e(TAG, "[SIGNALCTRLThread] ========== 17 ==========");
                        // CALL CONTROL
                        if (SIPStack.bVibrating) {
//  	  	 				Log.e(TAG, "[SIGNALCTRLThread] ========== 18 ==========");
                            if (!(SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED)) {
//  	  	 				   Log.e(TAG, "[SIGNALCTRLThread] ========== 19 ==========");
                                // SERVICE MESSAGE NEEDED
                                dialerVibrator(false);
                            }
                        }

                        if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.bResponsebackgroundcall &&
                                SIPController.sipCall.bResponsebackgroundcallReady && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {
//  	  	 				Log.e(TAG, "[SIGNALCTRLThread] ========== 20 ==========");

                            if (SIPStun.bBlackCallBackgroundMode) {
//  	  	 					Log.e(TAG, "[SIGNALCTRLThread] ========== 21 ==========");
                                if (SIPController.sipCall.bResponsebackgroundcallReady) {
//  	  	 						Log.e(TAG, "[SIGNALCTRLThread] ========== 22 ==========");
                                    Date currentTime = new Date();
                                    long durationMilliSeconds = Math.abs(currentTime.getTime() - SIPController.sipCall.responsebackgroundcallTimer.getTime());

                                    if (durationMilliSeconds > 1000) {
//  	  	 							Log.e(TAG, "[SIGNALCTRLThread] ========== 23 ==========");
                                        Log.i(TAG, "MILL TIME : " + durationMilliSeconds);
                                        SIPController.sipCall.responsebackgroundcallTimer = new Date();
                                        SIPController.sipCall.bResponsebackgroundcall = false;
                                        SIPController.sipCall.bResponsebackgroundcallReady = false;
                                        // SERVICE MESSAGE NEEDED
                                        // Log.i(TAG, "DEBUG 1");
                                        dialerNotifyIncomingCall(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                                        if (SIPStack.bDirectCall) {
//  	  	 								Log.e(TAG, "[SIGNALCTRLThread] ========== 24 ==========");
                                            dialerVideoSet(true);
                                        }
                                    }
                                }
                            } else {
//  	  	 					Log.e(TAG, "[SIGNALCTRLThread] ========== 25 ==========");
                                Date currentTime = new Date();
                                long durationSeconds = Math.abs((currentTime.getTime() - SIPController.sipCall.responsebackgroundcallTimer.getTime()) / 1000);
                                if (durationSeconds > 0) {
                                    SIPController.sipCall.bResponsebackgroundcall = false;
                                    // SERVICE MESSAGE NEEDED
                                    // Log.i(TAG, "DEBUG 2");
                                    dialerNotifyIncomingCall(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                                }
                            }
                        }

                        if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.bCancelRequest) {
                            Log.e(TAG, "========== STUN [1] ==========");
                            callTerminate();
                            SIPController.sipCall.bCancelRequest = false;
                        } else if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.bRejectRequest) {
                            Log.e(TAG, "========== STUN [2] ==========");
                            if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                                Log.e(TAG, "========== STUN [2-1] ==========");
                                if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                                    Log.e(TAG, "========== STUN [2-2] ==========");
                                    if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                                        Log.e(TAG, "========== STUN [2-3] ==========");
                                        Log.e(TAG, "[JEFF] ========== RTP END 16 ==========");
                                        SIPController.audioRTPManager.RTPEnd();
                                        // SERVICE MESSAGE NEEDED
                                        if (SIPStack.bDirectCall) {
                                            Log.e(TAG, "========== STUN [2-4] ==========");
                                            dialerVideoSet(false);
                                        }
                                    }
                                }
                            }
                            SIPController.sipCall.bRejectRequest = false;
                            SIPController.sipCall.bCancelRequest = true;
                        } else if (SIPController.sipCall != null && SIPController.sipCall.bNewcallRequest) {
                            Log.e(TAG, "========== STUN [3] ==========");
                            if (SIPController.sipCall.bDirectcall) {
                                Log.e(TAG, "========== STUN [3-1] ==========");
                                SIPController.sipCall.bNewcallRequest = false;
                                directcallActivate(SIPController.sipCall.number);
                            } else if (cmcore.regState == SIPStack.SIP_REGSTATE_REGISTERED) {
                                Log.e(TAG, "========== STUN [3-2] ==========");
                                SIPController.sipCall.bNewcallRequest = false;
                                callActivate(SIPController.sipCall.number);
                            }
                        } else if (SIPController.sipCall != null && SIPController.sipCall.bUpdateRequest) {
                            Log.e(TAG, "========== STUN [4] ==========");
                            if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CONNECTED) {
                                Log.e(TAG, "========== STUN [4-1] ==========");
                                sendHold();
                            }
                            SIPController.sipCall.bUpdateRequest = false;
                        } else if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.forward.bForward && SIPController.sipCall.bForwardRequest) {
                            Log.e(TAG, "========== STUN [5] ==========");
                            SIPController.sipCall.bForwardRequest = false;
                            if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                                Log.e(TAG, "========== STUN [5-1] ==========");
                                if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                                    Log.e(TAG, "========== STUN [5-2] ==========");
                                    if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                                        Log.e(TAG, "========== STUN [5-3] ==========");
                                        Log.e(TAG, "[JEFF] ========== RTP END 17 ==========");
                                        SIPController.audioRTPManager.RTPEnd();
                                        // SERVICE MESSAGE NEEDED
                                        if (SIPStack.bDirectCall) {
                                            Log.e(TAG, "========== STUN [5-4] ==========");
                                            dialerVideoSet(false);
                                        }
                                    }
                                }
                            }
                            Log.e(TAG, "========== STUN [5-5] ==========");
                            redirectTerminate(SIPController.forward.contact);
                            SIPController.forward.contact = " ";
                        } else {
//  	  	 				Log.e(TAG, "[SIGNALCTRLThread] ========== 26 ==========");
                            SIPCTRLCall();
                        }
                    }

                    if (cmcore.ctrlIndex == 0) cmcore.ctrlIndex = 1;
                    else cmcore.ctrlIndex = 0;
                } catch (Exception e) {
                    Log.e(TAG, "[Exception] SIGNALCTRLThread.while(cmcore.SIGNALCTRLRunning)");
                    e.printStackTrace();
                }
            }
            cmcore.SIGNALCTRLRunning = false;
            cmcore.SIGNALCTRLThread = null;
        }   // run()
    }

    class CTRLTimerTask extends TimerTask {
        public void run() {
            if (cmcore.SIGNALCTRLTimer == null) {
                Log.e(TAG, "cmcore.SIGNALCTRLTimer is null!! =====");
                return;
            }
            Log.w(TAG, "[CTRLTimerTask]");

            if (SIPStack.networkStatus != SIPStack.SIP_NETIF_AVAILABLE) {
                if (SIPStack.networkStatus == SIPStack.SIP_NETIF_UNREACHABLE) {
                    // SERVICE MESSAGE NEEDED
                    updateDialerStatus("NETWORK UNREACHABLE.", true);
                } else if (SIPStack.networkStatus == SIPStack.SIP_NETIF_UNAVAILABLE) {
                    //SERVICE MESSAGE NEEDED
                    updateDialerStatus("NETWORK not ready.", true);
                }

                if (SIPStack.networkStatus == SIPStack.SIP_NETIF_UNAVAILABLE || SIPStack.networkStatus == SIPStack.SIP_NETIF_UNREACHABLE) {
                    if (connectivityManager != null && connectivityManager.getActiveNetworkInfo() != null) {
                        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();

                        switch (activeNetwork.getType()) {

                            case ConnectivityManager.TYPE_WIMAX: // 4g 망 체크

                                if (SIPStack.isInternetWiMax == false && SIPStack.bBackgroundRunning)
                                    SIPStack.bShutdownApplication = true;

                                SIPStack.isInternetWiMax = true;
                                SIPStack.isInternetWiFi = false;
                                SIPStack.isInternetMobile = false;
                                SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                                break;

                            case ConnectivityManager.TYPE_WIFI: // wifi망 체크

                                if (SIPStack.isInternetWiFi == false && SIPStack.bBackgroundRunning)
                                    SIPStack.bShutdownApplication = true;
                                SIPStack.isInternetWiMax = false;
                                SIPStack.isInternetWiFi = true;
                                SIPStack.isInternetMobile = false;
                                SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                                break;

                            case ConnectivityManager.TYPE_MOBILE: // 3g 망 체크

                                if (SIPStack.isInternetMobile == false && SIPStack.bBackgroundRunning)
                                    SIPStack.bShutdownApplication = true;
                                SIPStack.isInternetWiMax = false;   // false;
                                SIPStack.isInternetWiFi = false;
                                SIPStack.isInternetMobile = true;
                                SIPStack.PRIMARY_CODEC_AUDIO = SIPStack.SIP_CODEC_G711U;
                                break;

                        }
                    }

                    cmcore.netcheckIntervalTimer = new Date();

                    try {
                        String host = SIPController.getSHVE140SLocalIpAddress();
                        cmcore.action_net_1(host);
                    } catch (Exception e) {
                        Log.e(TAG, "[Exception] String host = SIPController.getSHVE140SLocalIpAddress()");
                    }
                }
                return;
            }

            if (SIPStack.bDirectCall == false && cmcore.regState != SIPStack.SIP_REGSTATE_REGISTERED) {
                if (cmcore.action_net_0()) sendRegister();
            }

            // REGIST CONTROL
            if (cmcore.ctrlIndex == 0) {
                if (SIPStack.bShutdownApplication) {
                    if (SIPStack.bDirectCall == false) sendUNRegister();
                    SIPStack.bShutdownApplication = false;
                    // SERVICE MESSAGE NEEDED
                    dialerShutdownApplication();
                }

                if (SIPStack.bDirectCall == false) SIPCTRLRegister();
            } else if (cmcore.ctrlIndex == 1) {
                // CALL CONTROL
                if (SIPStack.bVibrating) {
                    if (!(SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED)) {
                        // SERVICE MESSAGE NEEDED
                        dialerVibrator(false);
                    }
                }

                if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.bResponsebackgroundcall &&
                        SIPController.sipCall.bResponsebackgroundcallReady && SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_OFFERRED) {

                    if (SIPStun.bBlackCallBackgroundMode) {
                        if (SIPController.sipCall.bResponsebackgroundcallReady) {
                            Date currentTime = new Date();
                            int durationMilliSeconds = (int) (currentTime.getTime() - SIPController.sipCall.responsebackgroundcallTimer.getTime());

                            if (durationMilliSeconds > 1000) {
                                Log.i(TAG, "MILL TIME : " + durationMilliSeconds);
                                SIPController.sipCall.responsebackgroundcallTimer = new Date();
                                SIPController.sipCall.bResponsebackgroundcall = false;
                                SIPController.sipCall.bResponsebackgroundcallReady = false;
                                // SERVICE MESSAGE NEEDED
                                // Log.i(TAG, "DEBUG 1");
                                dialerNotifyIncomingCall(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                                if (SIPStack.bDirectCall) {
                                    dialerVideoSet(true);
                                }
                            }
                        }
                    } else {
                        Date currentTime = new Date();
                        int durationSeconds = (int) (currentTime.getTime() - SIPController.sipCall.responsebackgroundcallTimer.getTime()) / 1000;
                        if (durationSeconds > 0) {
                            SIPController.sipCall.bResponsebackgroundcall = false;
                            // SERVICE MESSAGE NEEDED
                            // Log.i(TAG, "DEBUG 2");
                            dialerNotifyIncomingCall(SIPController.sipCall.dnis, SIPController.sipCall.dnis + "@" + SIPController.sipCall.remoteIp + ":" + SIPController.sipCall.remotePort);
                        }
                    }
                }

                if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.bCancelRequest) {
                    callTerminate();
                    SIPController.sipCall.bCancelRequest = false;
                } else if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.sipCall.bRejectRequest) {
                    if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                        if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                                Log.e(TAG, "[JEFF] ========== RTP END 14 ==========");
                                SIPController.audioRTPManager.RTPEnd();
                                // SERVICE MESSAGE NEEDED
                                if (SIPStack.bDirectCall) dialerVideoSet(false);
                            }
                        }
                    }
                    SIPController.sipCall.bRejectRequest = false;
                    SIPController.sipCall.bCancelRequest = true;
                } else if (SIPController.sipCall != null && SIPController.sipCall.bNewcallRequest) {
                    Log.i(TAG, "[CTRLTimerTask] ========== CALL START ==========");
                    if (SIPController.sipCall.bDirectcall) {
                        SIPController.sipCall.bNewcallRequest = false;
                        directcallActivate(SIPController.sipCall.number);
                    } else if (cmcore.regState == SIPStack.SIP_REGSTATE_REGISTERED) {
                        SIPController.sipCall.bNewcallRequest = false;
                        callActivate(SIPController.sipCall.number);
                    }
                } else if (SIPController.sipCall != null && SIPController.sipCall.bUpdateRequest) {
                    if (SIPController.sipCall.callState == SIPStack.SIP_CALLSTATE_CONNECTED) {
                        sendHold();
                    }
                    SIPController.sipCall.bUpdateRequest = false;
                } else if (SIPController.sipCall != null && SIPController.sipCall.flag && SIPController.forward.bForward && SIPController.sipCall.bForwardRequest) {
                    SIPController.sipCall.bForwardRequest = false;
                    if (SIPController.sipCall.remoteSdp != null && SIPController.sipCall.remoteSdp.flag && SIPController.audioRTPManager != null) {
                        if (SIPController.sipCall.remoteSdp.audioM != null && SIPController.sipCall.remoteSdp.audioM.flag) {
                            if (SIPController.sipCall.sdp != null && SIPController.sipCall.sdp.audioM != null && SIPController.audioRTPManager != null) {
                                Log.e(TAG, "[JEFF] ========== RTP END 15 ==========");
                                SIPController.audioRTPManager.RTPEnd();
                                // SERVICE MESSAGE NEEDED
                                if (SIPStack.bDirectCall) dialerVideoSet(false);
                            }
                        }
                    }
                    redirectTerminate(SIPController.forward.contact);
                    SIPController.forward.contact = "";
                } else {
                    SIPCTRLCall();
                }
            }

            if (cmcore.ctrlIndex == 0) cmcore.ctrlIndex = 1;
            else cmcore.ctrlIndex = 0;
        }
    }

    private void registerSIPStunBR() {
        try {
            Log.i(TAG, "[registerSIPStunBR] ===== START =====");
            IntentFilter mIntentFilter = new IntentFilter();
            mIntentFilter.addAction(Declare.PrivateBR.APPLIVESIGNAL);
            registerReceiver(procSIPStunBR, mIntentFilter);
            Log.i(TAG, "[registerSIPStunBR] ===== DONE =====");
        } catch (Exception e) {
            Log.e(TAG, "[Exception] registerSIPStunBR()");
            e.printStackTrace();
        }
    }

    BroadcastReceiver procSIPStunBR = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            try {
                String strActionName = intent.getAction();
                Log.i(TAG, "[procSIPStunBR] strActionName [" + strActionName+ "]");
                if (strActionName.equals(Declare.PrivateBR.APPLIVESIGNAL)) {
                    nAppLiveCnt = APP_LIVE_TIMEOUT;
                }
            } catch (Exception e) {
                Log.e(TAG, "[Exception] onReceive(Context context, Intent intent)");
                e.printStackTrace();
            }
        }
    };

    /**
     * 어플리케이션 Live 상태를 BR을 통해 수신한다.
     * 1초에 한 번씩 수신하며, 총 5회 연속으로 미수신시 MainActivity를 재실행 한다. (JEFF, 2019.10.08)
     */
    private int APP_LIVE_TIMEOUT = 5;
    private int APP_LIVE_TIMEOUT_RESTART = 20;
    private int nAppLiveCnt = APP_LIVE_TIMEOUT;
    private AppLiveSignalChecker mAppLiveSignalChecker;
    private void startAppLiveSignalChecker() {
        try {
            Log.w(TAG, "[startAppLiveSignalChecker] ===== START =====");
            mAppLiveSignalChecker = new AppLiveSignalChecker();
            mAppLiveSignalChecker.start();
        } catch (Exception e) {
            Log.e(TAG, "[Exception] startAppLiveSignalChecker()");
            e.printStackTrace();
        }
    }
    private class AppLiveSignalChecker extends Thread {

        boolean bRun = true;

        public AppLiveSignalChecker() {
            Log.w(TAG, "[AppLiveSignalChecker] init AppLiveSignalChecker!!");
        }

        public void stopThread() {
            try {
                bRun = false;
            } catch (Exception e) {
                Log.e(TAG, "[Exception] AppLiveSignalChecker.stopThread()");
                e.printStackTrace();
            }
        }

        public void run() {
            try {
                Thread.sleep(10000);
                while (bRun) {
                    nAppLiveCnt--;
                    if (nAppLiveCnt <= 0) {
                        // 재부팅
                        Log.w(TAG, "[AppLiveSignalChecker.run()] ========== REBOOT ==========");
                        MainActivity.mIOInterface.Reboot(0);
                        nAppLiveCnt = APP_LIVE_TIMEOUT_RESTART;
                    }
                    Thread.sleep(1000);
                }
            } catch (Exception e) {
                Log.e(TAG, "[Exception] AppLiveSignalChecker().run()");
                e.printStackTrace();
            }
            Log.i(TAG, "[AppLiveSignalChecker().run()] ========== END ==========");
        }
    }

    /**
     * 통화 앱 꼬임시 임시 보완 코드
     */
    public void killProcess() {
        try {
            Log.i(TAG, "[killProcess] ===== START =====");
            int pid = android.os.Process.myPid();
            android.os.Process.killProcess(pid);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] killProcess()");
            e.printStackTrace();
        }
    }

    private void startMainActivity() {
        try {
            Log.i(TAG, "[startMainActivity] ===== START =====");
            Intent mIntent = new Intent(Intent.ACTION_MAIN);
            mIntent.setComponent(new ComponentName("kr.co.icontrols.ilp300_700", "kr.co.icontrols.ilp300_700.MainActivity"));
            mIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
            mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            getApplicationContext().startActivity(mIntent);
            nAppLiveCnt = APP_LIVE_TIMEOUT_RESTART;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] startMainActivity()");
            e.printStackTrace();
        }
    }
    // yjyoon
    public class mySocket extends Thread {

        Socket s;
        String toCall;
        BufferedWriter output;
        BufferedReader input;
        String message;
        Handler handler;

        public mySocket (String toCall, String msg, Handler handler) {
            this.toCall = toCall;
            this.message = msg;
            this.handler = handler;
        }

        @Override
        public void run() {
            try {
                s = new Socket(toCall, 4001);

                output = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
                input = new BufferedReader(new InputStreamReader(s.getInputStream()));

                int what = -1;

                while (input != null) {
                    output.write(message);
                    output.flush();
                    String msg = input.readLine();
                    if (msg != null) {
                        if (msg.equals("ACK")) {
                            switch (message) {
                                case "I_AM_HERE":

                                    break;
                            }
                            break;
                        }
                    }
                }
                if (s != null)
                    s.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public CallManager.CALLTYPE makeCallType(String strIPAddress) {
        CallManager.CALLTYPE strType = CallManager.CALLTYPE.RESIDENCE;
        try {
            Log.i(TAG,"[makeSIPID] strIPAddress : " + strIPAddress);

            String[] IP_Parse = strIPAddress.split("\\.");


            if (IP_Parse[2].equals("128")) {
                // 경비실폰
                strType = CallManager.CALLTYPE.GUARD;
            } else if (IP_Parse[2].equals("0")) {
                // 로비폰
                strType = CallManager.CALLTYPE.LOBBY;
            } else if (IP_Parse[2].equals("201")) {
                // 아이허브
                strType = CallManager.CALLTYPE.IHUB;
            } else {
                strType = CallManager.CALLTYPE.RESIDENCE;

            }

            Log.i(TAG,"[makeSIPID] SIPID : " + strType.toString());

            return strType;
        } catch (Exception e) {
            Log.e(TAG, "[Exception] MakeSIPID(...) : " + e);
            e.printStackTrace();
        }

        return strType;

    }

    CallManager.CALLEVENTTYPE cALLEVENTTYPE = CallManager.CALLEVENTTYPE.SIP_RECEIVE_CALL;
    CallManager.CALLTYPE cALLTYPE = CallManager.CALLTYPE.NONE;

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);

            int what = msg.what;
            String message = null;
            Intent Intent = new Intent();

            Log.v("yjyoon", "Handler what=" + what);

            switch(what) {
                case 100: // from server.
                    clientIP = (String)msg.obj;

                    message = "I_AM_HERE";
                    break;
                case 101: // from BYE
                    message = null;
                    clientIP = (String)msg.obj;
                    cALLEVENTTYPE = CallManager.CALLEVENTTYPE.SIP_TERMINATE_CALL;
                    cALLTYPE = CallManager.CALLTYPE.NONE;
                    cALLTYPE = makeCallType(clientIP);

                    Intent.setAction(Declare.PrivateBR.CERES_CALL);
                    Intent.putExtra(Declare.CALLTRIGGER.CALLEVENTTYPE, cALLEVENTTYPE.toString());
                    Intent.putExtra(Declare.CALLTRIGGER.CALLTYPE, cALLTYPE.toString());
                    Intent.putExtra(Declare.CALLTRIGGER.REMOTEINFO, clientIP);
                    mContext.sendBroadcast(Intent);
                    //mCallController.onCeresCallEvent(Intent);
                    break;
                case 102: // from I_AM_TALKING
                    //int i = mCMIF.CERES_MakeCall(clientIP, 1);        // 1 : audio, 2: video, 3: audio+video
                    //Log.v("yjyoon", "mCMIF.CERES_MakeCall " + i);
                    clientIP = (String)msg.obj;
                    message = null;
                    cALLEVENTTYPE = CallManager.CALLEVENTTYPE.SIP_RECEIVE_CALL;
                    cALLTYPE = CallManager.CALLTYPE.NONE;
                    cALLTYPE = makeCallType(clientIP);

                    Intent.setAction(Declare.PrivateBR.CERES_CALL);
                    Intent.putExtra(Declare.CALLTRIGGER.CALLEVENTTYPE, cALLEVENTTYPE.toString());
                    Intent.putExtra(Declare.CALLTRIGGER.CALLTYPE, cALLTYPE.toString());
                    Intent.putExtra(Declare.CALLTRIGGER.REMOTEINFO, clientIP);
                    mContext.sendBroadcast(Intent);

                    //mCallController.onCeresCallEvent(Intent);
                    break;
                case 103: // from I_AM_TALKING
                    //int i = mCMIF.CERES_MakeCall(clientIP, 1);        // 1 : audio, 2: video, 3: audio+video
                    //Log.v("yjyoon", "mCMIF.CERES_MakeCall " + i);
                    clientIP = (String)msg.obj;
                    message = "null";

                    cALLEVENTTYPE = CallManager.CALLEVENTTYPE.SIP_REJECT_BUSY_CALL;
                    cALLTYPE = CallManager.CALLTYPE.NONE;
                    cALLTYPE = makeCallType(clientIP);

                    Intent.setAction(Declare.PrivateBR.CERES_CALL);
                    Intent.putExtra(Declare.CALLTRIGGER.CALLEVENTTYPE, cALLEVENTTYPE.toString());
                    Intent.putExtra(Declare.CALLTRIGGER.CALLTYPE, cALLTYPE.toString());
                    Intent.putExtra(Declare.CALLTRIGGER.REMOTEINFO, clientIP);
                    mContext.sendBroadcast(Intent);

                    //mCallController.onCeresCallEvent(Intent);
                    break;
                case 104: // from I_AM_TALKING
                    //int i = mCMIF.CERES_MakeCall(clientIP, 1);        // 1 : audio, 2: video, 3: audio+video
                    //Log.v("yjyoon", "mCMIF.CERES_MakeCall " + i);
                    clientIP = (String)msg.obj;
                    message = "null";
                    Intent.setAction(Declare.PrivateBR.REDIRECT_CALL);
                    Intent.putExtra(Declare.CALLTRIGGER.REMOTEINFO, clientIP);
                    mContext.sendBroadcast(Intent);

                    //mCallController.onCeresCallEvent(Intent);
                    break;
            }

            if (message != null) {
                mySocket s = new mySocket(clientIP, message, mHandler);
                s.start();
            }
        }
    };




}