/** This is a listener method. */
  public void processResponse(ResponseEvent responseEvent) {
    try {

      Response response = responseEvent.getResponse();
      SipProvider sipProvider = (SipProvider) responseEvent.getSource();
      ClientTransaction clientTransaction = responseEvent.getClientTransaction();

      ProxyDebug.println(
          "\n***************************************************************"
              + "\n***************************************************************"
              + "\nResponse "
              + response.getStatusCode()
              + " "
              + response.getReasonPhrase()
              + " received:\n"
              + response.toString());
      ProxyDebug.println("Processing Response in progress");

      if (ProxyDebug.debug) ProxyUtilities.printTransaction(clientTransaction);

      // Henrik - added handling of responses addressed to server
      // If we use a presenceserver, and if statuscode was OK...
      CSeqHeader cseqHeader = (CSeqHeader) response.getHeader(CSeqHeader.NAME);

      if (cseqHeader.getMethod().equals("SUBSCRIBE")) {
        presenceServer.processSubscribeResponse((Response) response.clone(), clientTransaction);
      } else if (cseqHeader.getMethod().equals("NOTIFY")) {
        // presenceServer.processNotifyResponse((Response)response.clone(),
        // clientTransaction);
      }

      responseForwarding.forwardResponse(sipProvider, response, clientTransaction);

    } catch (Exception ex) {
      if (ProxyDebug.debug) {
        ProxyDebug.println("Proxy, processResponse(), internal error, " + "exception raised:");
        ProxyDebug.logException(ex);
      }
    }
  }
  public void processResponse(ResponseEvent responseReceivedEvent) {
    /// System.out.println("=> BUNDLE: br.ufes.inf.ngn.televoto.client.logic | CLASS: LogicListener
    // | METOD: processResponse ");//By Ju
    try {
      Response myResponse = responseReceivedEvent.getResponse();
      logger.info("<<< " + myResponse.toString());

      ClientTransaction thisClientTransaction = responseReceivedEvent.getClientTransaction();

      int myStatusCode = myResponse.getStatusCode();

      switch (status) {
        case WAIT_PROV:
          if (!thisClientTransaction.equals(myClientTransaction))
            myClientTransaction = thisClientTransaction;

          if (myStatusCode < 200) {
            status = WAIT_FINAL;
            myDialog = thisClientTransaction.getDialog();
          } else if (myStatusCode < 300) {
            myDialog = thisClientTransaction.getDialog();
            CSeqHeader originalCSeq =
                (CSeqHeader) myClientTransaction.getRequest().getHeader(CSeqHeader.NAME);
            long numseq = originalCSeq.getSeqNumber();
            Request myAck = myDialog.createAck(numseq);
            myAck.addHeader(myContactHeader);
            myDialog.sendAck(myAck);
            // logger.info(">>> "+myAck.toString());
            status = ESTABLISHED;
            byte[] cont = (byte[]) myResponse.getContent();
            answerInfo = mySdpManager.getSdp(cont);

          } else {
            if (myStatusCode == 401) {

            } else {
              status = IDLE;
              CSeqHeader originalCSeq =
                  (CSeqHeader) myClientTransaction.getRequest().getHeader(CSeqHeader.NAME);
              long numseq = originalCSeq.getSeqNumber();
              Request myAck = myDialog.createAck(numseq);
              myAck.addHeader(myContactHeader);
              myDialog.sendAck(myAck);
              // logger.info(">>> "+myAck.toString());
            }
          }
          break;

        case WAIT_FINAL:
          if (!thisClientTransaction.equals(myClientTransaction))
            myClientTransaction = thisClientTransaction;

          if (myStatusCode < 200) {
            status = WAIT_FINAL;
            myDialog = thisClientTransaction.getDialog();
          } else if (myStatusCode < 300) {
            if (useQueue.equals("yes")) {
              status = IDLE;
            } else {
              status = ESTABLISHED;
            }

            myDialog = thisClientTransaction.getDialog();
            CSeqHeader originalCSeq =
                (CSeqHeader) myClientTransaction.getRequest().getHeader(CSeqHeader.NAME);
            long numseq = originalCSeq.getSeqNumber();
            Request myAck = myDialog.createAck(numseq); // Aquiiii
            myAck.addHeader(myContactHeader);
            myDialog.sendAck(myAck);
            // logger.info(">>> "+myAck.toString());
            byte[] cont = (byte[]) myResponse.getContent();
            answerInfo = mySdpManager.getSdp(cont);

          } else {
            // Cancelando requisição ao cliente
            Request myCancelRequest = myClientTransaction.createCancel();
            ClientTransaction myCancelClientTransaction =
                mySipProvider.getNewClientTransaction(myCancelRequest);
            myCancelClientTransaction.sendRequest();
            // logger.info(">>> " + myCancelRequest.toString());
            status = IDLE;
          }
          break;

        case REGISTERING:
          if (!thisClientTransaction.equals(myClientTransaction))
            myClientTransaction = thisClientTransaction;

          if (myStatusCode == 200) {
            status = IDLE;
            if (!Unregistring) {

              System.out.println(myName + ": Registrado");

              // inserir captura de timestamp
              // logger.info(myName + ";INVITE;" +  getTime());
              // Random gerador = new Random();
              // int temp = gerador.nextInt(10);
              // System.out.println(myName + ": Esperando " + temp + "segundos");
              // Thread.sleep(temp);

              System.out.println(myName + ": chamando " + destination);

              SdpInfo offerInfo = new SdpInfo();
              offerInfo.IpAddress = myIP;
              offerInfo.aport = myAudioPort;
              offerInfo.aformat = 0;
              byte[] content = mySdpManager.createSdp(offerInfo);

              // Via
              // ViaHeader comentei
              myViaHeader = myHeaderFactory.createViaHeader(myIP, myPort, "udp", null);
              myViaHeader.setRPort();
              ArrayList viaHeaders = new ArrayList();
              viaHeaders.add(myViaHeader);

              // From
              Address addressOfRecord = myAddressFactory.createAddress("<sip:" + myUserID + ">");
              FromHeader myFromHeader = myHeaderFactory.createFromHeader(addressOfRecord, "456249");

              // To
              String dstURI[] = destination.split("@");
              String dstSipAlias = dstURI[0];
              Address destinationAddress =
                  myAddressFactory.createAddress("<sip:" + destination + ">");
              javax.sip.address.URI myRequestURI = destinationAddress.getURI();
              ToHeader myToHeader = myHeaderFactory.createToHeader(destinationAddress, null);

              // MaxForwards
              MaxForwardsHeader myMaxForwardsHeader = myHeaderFactory.createMaxForwardsHeader(70);

              // Call-ID
              CallIdHeader myCallIdHeader = mySipProvider.getNewCallId();

              // CSeq
              Random random = new Random();
              CSeqHeader myCSeqHeader =
                  myHeaderFactory.createCSeqHeader(random.nextInt(1000) * 1L, "INVITE");

              // Create SIP request
              Request myRequest =
                  myMessageFactory.createRequest(
                      myRequestURI,
                      "INVITE",
                      myCallIdHeader,
                      myCSeqHeader,
                      myFromHeader,
                      myToHeader,
                      viaHeaders,
                      myMaxForwardsHeader);

              // Contact
              Address contactAddress =
                  myAddressFactory.createAddress(
                      "<sip:" + mySipAlias + "@" + myIP + ":" + myPort + ";transport=udp>");
              myContactHeader = myHeaderFactory.createContactHeader(contactAddress);
              myRequest.addHeader(myContactHeader);

              // Allow
              Allow myAllow = new Allow();
              myAllow.setMethod(
                  "INVITE, ACK, CANCEL, BYE, MESSAGE, OPTIONS, NOTIFY, PRACK, UPDATE, REFER");
              myRequest.addHeader(myAllow);

              // Privacy
              Privacy myPrivacy = new Privacy("none");
              myRequest.addHeader(myPrivacy);

              // PPreferredIdentity
              HeaderFactoryImpl myHeaderFactoryImpl = new HeaderFactoryImpl();
              PPreferredIdentityHeader myPPreferredIdentityHeader =
                  myHeaderFactoryImpl.createPPreferredIdentityHeader(
                      myAddressFactory.createAddress("sip:" + myName + '@' + myServer));
              myRequest.addHeader(myPPreferredIdentityHeader);

              // Route
              Address routeAddress =
                  myAddressFactory.createAddress("sip:orig@scscf." + myServer + ":6060;lr");
              // RouteHeader comentei
              myRouteHeader = myHeaderFactory.createRouteHeader(routeAddress);
              myRequest.addHeader(myRouteHeader);

              // Para proxy funcionar
              SipURI outboundProxyURI = myAddressFactory.createSipURI("proxy", myProxyIP);
              outboundProxyURI.setLrParam();
              outboundProxyURI.setPort(myProxyPort);
              myRouteHeader =
                  myHeaderFactory.createRouteHeader(
                      myAddressFactory.createAddress(outboundProxyURI));
              myRequest.addFirst(myRouteHeader);

              // Content Type
              ContentTypeHeader contentTypeHeader =
                  myHeaderFactory.createContentTypeHeader("application", "sdp");
              myRequest.setContent(content, contentTypeHeader);

              // ClientTransaction comentei aqui
              myClientTransaction = mySipProvider.getNewClientTransaction(myRequest);
              myClientTransaction.setRetransmitTimer(700);
              myClientTransaction.sendRequest();

              status = WAIT_PROV;

              logger.info(">>> " + myRequest.toString());

            } else {
              this.setOff(mySipStack);
            }
          } else {
            if (myStatusCode == 403) {

              System.out.println("Problemas com credenciais!!!!\n");
            } else if (myStatusCode == 401) {

              myName = (String) this.getLocalName();
              myUserID = (String) this.getLocalName() + "@" + myServer;

              Address contactAddress =
                  myAddressFactory.createAddress("sip:" + myName + '@' + myIP + ":" + myPort);
              myContactHeader = myHeaderFactory.createContactHeader(contactAddress);

              myViaHeader = myHeaderFactory.createViaHeader(myIP, myPort, "udp", null);

              fromAddress = myAddressFactory.createAddress(myName + " <sip:" + myUserID + ">");

              Address registrarAddress = myAddressFactory.createAddress("sip:" + myServer);
              Address registerToAddress = fromAddress;
              Address registerFromAddress = fromAddress;

              ToHeader myToHeader = myHeaderFactory.createToHeader(registerToAddress, null);
              FromHeader myFromHeader =
                  myHeaderFactory.createFromHeader(registerFromAddress, "647554");

              ArrayList myViaHeaders = new ArrayList();
              myViaHeaders.add(myViaHeader);

              // System.out.println("myClientTransaction.getRequest():"+
              // myClientTransaction.getRequest());
              CSeqHeader originalCSeq =
                  (CSeqHeader) myClientTransaction.getRequest().getHeader(CSeqHeader.NAME);
              long numseq = originalCSeq.getSeqNumber();
              MaxForwardsHeader myMaxForwardsHeader = myHeaderFactory.createMaxForwardsHeader(70);
              CSeqHeader myCSeqHeader = myHeaderFactory.createCSeqHeader(numseq + 1L, "REGISTER");

              CallIdHeader myCallID =
                  (CallIdHeader) myClientTransaction.getRequest().getHeader(CallIdHeader.NAME);
              CallIdHeader myCallIDHeader = myCallID;
              SipURI myRequestURI = (SipURI) registrarAddress.getURI();
              Request myRegisterRequest =
                  myMessageFactory.createRequest(
                      myRequestURI,
                      "REGISTER",
                      myCallIDHeader,
                      myCSeqHeader,
                      myFromHeader,
                      myToHeader,
                      myViaHeaders,
                      myMaxForwardsHeader);
              myRegisterRequest.addHeader(myContactHeader);

              // Expires
              ExpiresHeader myExpiresHeader;
              if (Unregistring) {
                myExpiresHeader = myHeaderFactory.createExpiresHeader(0);
                myContactHeader.setExpires(0);
              } else {
                myExpiresHeader = myHeaderFactory.createExpiresHeader(60000);
              }
              myRegisterRequest.addHeader(myExpiresHeader);

              // Allow
              Allow myAllow = new Allow();
              myAllow.setMethod(
                  "INVITE, ACK, CANCEL, BYE, MESSAGE, OPTIONS, NOTIFY, PRACK, UPDATE, REFER");
              myRegisterRequest.addHeader(myAllow);

              // Privacy
              Privacy myPrivacy = new Privacy("none");
              myRegisterRequest.addHeader(myPrivacy);

              // PPreferredIdentity
              HeaderFactoryImpl myHeaderFactoryImpl = new HeaderFactoryImpl();
              PPreferredIdentityHeader myPPreferredIdentityHeader =
                  myHeaderFactoryImpl.createPPreferredIdentityHeader(
                      myAddressFactory.createAddress("sip:" + myName + '@' + myServer));
              myRegisterRequest.addHeader(myPPreferredIdentityHeader);

              // Supported
              Supported mySupported = new Supported("path");
              myRegisterRequest.addHeader(mySupported);

              myWWWAuthenticateHeader =
                  Utils.makeAuthHeader(
                      myHeaderFactory, myResponse, myRegisterRequest, myUserID, myPassword);
              myRegisterRequest.addHeader(myWWWAuthenticateHeader);

              myClientTransaction = mySipProvider.getNewClientTransaction(myRegisterRequest);
              myClientTransaction.sendRequest();

              // logger.info(">>> "+myRegisterRequest.toString());
              // System.out.println(">>> " + myRegisterRequest.toString());
              status = REGISTERING;
            }
          }
          break;
      }
    } catch (Exception excep) {
      excep.printStackTrace();
    }
  }
  public void processSubscribe(Request request, ServerTransaction serverTransaction) {
    logger.debug("Processing SUBSCRIBE in progress ");
    try {

      MessageFactory messageFactory = imUA.getMessageFactory();
      HeaderFactory headerFactory = imUA.getHeaderFactory();
      AddressFactory addressFactory = imUA.getAddressFactory();
      Dialog dialog = serverTransaction.getDialog();

      // ********** Terminating subscriptions **********
      ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(ExpiresHeader.NAME);
      if (expiresHeader != null && expiresHeader.getExpires() == 0) {
        if (dialog != null) {
          // Terminating an existing subscription
          Response response = messageFactory.createResponse(Response.OK, request);
          serverTransaction.sendResponse(response);
          IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
          imNotifyProcessing.sendNotify(response, null, dialog);
          return;
        } else {
          // Terminating an non existing subscription
          Response response =
              messageFactory.createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST, request);
          serverTransaction.sendResponse(response);
          return;
        }
      }

      // ********** Non-terminating subscriptions ************

      // send a 202 Accepted while waiting for authorization from user
      Response response = messageFactory.createResponse(Response.ACCEPTED, request);
      // Tag:
      ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
      if (toHeader.getTag() == null)
        toHeader.setTag(new Integer((int) (Math.random() * 10000)).toString());
      serverTransaction.sendResponse(response);
      logger.debug(response.toString());

      // We have to ask the user to authorize the guy to be in his buddy
      // list
      String presentityURL = IMUtilities.getKey(request, "From");
      SipProvider sipProvider = imUA.getSipProvider();
      InstantMessagingGUI imGUI = imUA.getInstantMessagingGUI();
      boolean authorization = imGUI.getAuthorizationForBuddy(presentityURL);
      if (authorization) {
        logger.debug(
            "DEBUG: SubscribeProcessing, processSubscribe(), " + " Response 202 Accepted sent.");

        // We have to create or update the subscriber!
        PresenceManager presenceManager = imUA.getPresenceManager();
        String subscriberURL = IMUtilities.getKey(request, "From");

        if (dialog != null) presenceManager.addSubscriber(subscriberURL, response, dialog);
        else {
          logger.debug(
              "ERROR, IMSubscribeProcessing, processSubscribe(), the"
                  + " dialog for the SUBSCRIBE we received is null!!! No subscriber added....");
          return;
        }

        // Let's see if this buddy is in our buddy list
        // if not let's ask to add him!
        BuddyList buddyList = imGUI.getBuddyList();
        ListenerInstantMessaging listenerIM = imGUI.getListenerInstantMessaging();
        if (!buddyList.hasBuddy(subscriberURL)) {
          // Let's ask:
          listenerIM.addContact(subscriberURL);
        }

        /** ********************** send NOTIFY ************************* */
        // We send a NOTIFY for any of our status but offline
        String localStatus = listenerIM.getLocalStatus();
        if (!localStatus.equals("offline")) {
          IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
          Subscriber subscriber = presenceManager.getSubscriber(subscriberURL);
          // Response okSent=subscriber.getOkSent();

          subscriberURL = subscriber.getSubscriberName();

          String contactAddress = imUA.getIMAddress() + ":" + imUA.getIMPort();

          String subStatus = listenerIM.getLocalStatus();
          String status = null;
          if (subStatus.equals("offline")) status = "closed";
          else status = "open";
          String xmlBody =
              imNotifyProcessing.xmlPidfParser.createXMLBody(
                  status, subStatus, subscriberURL, contactAddress);
          imNotifyProcessing.sendNotify(response, xmlBody, dialog);
        }
      } else {
        // User did not authorize subscription. Terminate it!
        logger.debug(
            "DEBUG, IMSubsribeProcessing, processSubscribe(), " + " Subscription declined!");
        logger.debug(
            "DEBUG, IMSubsribeProcessing, processSubscribe(), "
                + " Sending a Notify with Subscribe-state=terminated");

        IMNotifyProcessing imNotifyProcessing = imUA.getIMNotifyProcessing();
        if (dialog != null) {
          imNotifyProcessing.sendNotify(response, null, dialog);
          logger.debug(
              "DEBUG, IMSubsribeProcessing, processSubscribe(), "
                  + " Sending a Notify with Subscribe-state=terminated");
        } else {
          logger.debug(
              "ERROR, IMSubscribeProcessing, processSubscribe(), the"
                  + " dialog for the SUBSCRIBE we received is null!!! \n"
                  + "   No terminating Notify sent");
        }
        imNotifyProcessing.sendNotify(response, null, dialog);
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  /** This is a listener method. */
  public void processRequest(RequestEvent requestEvent) {
    Request request = requestEvent.getRequest();
    SipProvider sipProvider = (SipProvider) requestEvent.getSource();
    ServerTransaction serverTransaction = requestEvent.getServerTransaction();
    try {

      if (ProxyDebug.debug)
        ProxyDebug.println(
            "\n****************************************************"
                + "\nRequest "
                + request.getMethod()
                + " received:\n"
                + request.toString());

      if (ProxyDebug.debug) ProxyUtilities.printTransaction(serverTransaction);

      /** **************************************************************************** */
      /** ********************* PROXY BEHAVIOR *********************************** */
      /** **************************************************************************** */

      /*
       * RFC 3261: 16.2: For all new requests, including any with unknown
       * methods, an element intending to proxy the request MUST:
       *
       * 1. Validate the request (Section 16.3)
       *
       * 2. Preprocess routing information (Section 16.4)
       *
       * 3. Determine target(s) for the request (Section 16.5)
       *
       * 4. Forward the request to each target (Section 16.6)
       *
       * 5. Process all responses (Section 16.7)
       */

      /** **************************************************************************** */
      /** *************************** 1. Validate the request (Section 16.3) ********* */
      /** **************************************************************************** */

      /*
       * Before an element can proxy a request, it MUST verify the
       * message's validity
       */

      RequestValidation requestValidation = new RequestValidation(this);
      if (!requestValidation.validateRequest(sipProvider, request, serverTransaction)) {
        // An appropriate response has been sent back by the request
        // validation step, so we just return. The request has been
        // processed!
        if (ProxyDebug.debug)
          ProxyDebug.println(
              "Proxy, processRequest(), the request has not been"
                  + " validated, so the request is discarded "
                  + " (an error code has normally been"
                  + " sent back)");
        return;
      }

      // Let's check if the ACK is for the proxy: if there is no Route
      // header: it is mandatory for the ACK to be forwarded
      if (request.getMethod().equals(Request.ACK)) {
        ListIterator routes = request.getHeaders(RouteHeader.NAME);

        if (routes == null || !routes.hasNext()) {
          if (ProxyDebug.debug)
            ProxyDebug.println(
                "Proxy, processRequest(), "
                    + "the request is an ACK"
                    + " targeted for the proxy, we ignore it");
          return;
        }
        /* added code */
        CallID call_id = (CallID) request.getHeader(CallID.CALL_ID);
        String call_id_str = call_id.getCallId();
        TimeThreadController.Start(call_id_str);
        /* end of added code */

      }

      if (serverTransaction == null) {
        String method = request.getMethod();
        // Methods that creates dialogs, so that can
        // generate transactions
        if (method.equals(Request.INVITE) || method.equals(Request.SUBSCRIBE)) {
          try {
            serverTransaction = sipProvider.getNewServerTransaction(request);
            TransactionsMapping transactionsMapping =
                (TransactionsMapping) serverTransaction.getDialog().getApplicationData();
            if (transactionsMapping == null) {
              transactionsMapping = new TransactionsMapping(serverTransaction);
            }
          } catch (TransactionAlreadyExistsException e) {
            if (ProxyDebug.debug)
              ProxyDebug.println(
                  "Proxy, processRequest(), this request" + " is a retransmission, we drop it!");
          }
        }
      }

      /** ************************************************************************ */
      /** **** 2. Preprocess routing information (Section 16.4) ****************** */
      /** ************************************************************************ */

      /*
       * The proxy MUST inspect the Request-URI of the request. If the
       * Request-URI of the request contains a value this proxy previously
       * placed into a Record-Route header field (see Section 16.6 item
       * 4), the proxy MUST replace the Request-URI in the request with
       * the last value from the Route header field, and remove that value
       * from the Route header field. The proxy MUST then proceed as if it
       * received this modified request. ..... (idem to below:) 16.12. The
       * proxy will inspect the URI in the topmost Route header field
       * value. If it indicates this proxy, the proxy removes it from the
       * Route header field (this route node has been reached).
       */

      ListIterator routes = request.getHeaders(RouteHeader.NAME);
      if (routes != null) {
        if (routes.hasNext()) {
          RouteHeader routeHeader = (RouteHeader) routes.next();
          Address routeAddress = routeHeader.getAddress();
          SipURI routeSipURI = (SipURI) routeAddress.getURI();

          String host = routeSipURI.getHost();
          int port = routeSipURI.getPort();

          if (sipStack.getIPAddress().equals(host)) {
            Iterator lps = sipStack.getListeningPoints();
            while (lps != null && lps.hasNext()) {
              ListeningPoint lp = (ListeningPoint) lps.next();
              if (lp.getPort() == port) {
                if (ProxyDebug.debug)
                  ProxyDebug.println(
                      "Proxy, processRequest(),"
                          + " we remove the first route form "
                          + " the RouteHeader;"
                          + " it matches the proxy");
                routes.remove();
                break;
              }
            }
          }
        }
      }

      /*
       * If the Request-URI contains a maddr parameter, the proxy MUST
       * check to see if its value is in the set of addresses or domains
       * the proxy is configured to be responsible for. If the Request-URI
       * has a maddr parameter with a value the proxy is responsible for,
       * and the request was received using the port and transport
       * indicated (explicitly or by default) in the Request-URI, the
       * proxy MUST strip the maddr and any non-default port or transport
       * parameter and continue processing as if those values had not been
       * present in the request.
       */

      URI requestURI = request.getRequestURI();
      if (requestURI.isSipURI()) {
        SipURI requestSipURI = (SipURI) requestURI;
        if (requestSipURI.getMAddrParam() != null) {
          // The domain the proxy is configured to be responsible for
          // is defined
          // by stack_domain parameter in the configuration file:
          if (configuration.hasDomain(requestSipURI.getMAddrParam())) {
            if (ProxyDebug.debug)
              ProxyDebug.println(
                  "Proxy, processRequest(),"
                      + " The maddr contains a domain we are responsible for,"
                      + " we remove the mAddr parameter from the original"
                      + " request");
            // We have to strip the madr parameter:
            requestSipURI.removeParameter("maddr");
            // We have to strip the port parameter:
            if (requestSipURI.getPort() != 5060 && requestSipURI.getPort() != -1) {
              requestSipURI.setPort(5060);
            }
            // We have to strip the transport parameter:
            requestSipURI.removeParameter("transport");
          } else {
            // The Maddr parameter is not a domain we have to take
            // care of, we pass this check...
          }
        } else {
          // No Maddr parameter, we pass this check...
        }
      } else {
        // No SipURI, so no Maddr parameter, we pass this check...
      }

      /** *************************************************************************** */
      /** *********** 3. Determine target(s) for the request (Section 16.5) ********* */
      /** ************************************************************************** */
      /*
       * The set of targets will either be predetermined by the contents
       * of the request or will be obtained from an abstract location
       * service. Each target in the set is represented as a URI.
       */

      Vector targetURIList = new Vector();
      URI targetURI;

      /*
       * If the Request-URI of the request contains an maddr parameter,
       * the Request-URI MUST be placed into the target set as the only
       * target URI, and the proxy MUST proceed to Section 16.6.
       */

      if (requestURI.isSipURI()) {
        SipURI requestSipURI = (SipURI) requestURI;
        if (requestSipURI.getMAddrParam() != null) {
          targetURI = requestURI;
          targetURIList.addElement(targetURI);
          if (ProxyDebug.debug)
            ProxyDebug.println(
                "Proxy, processRequest(),"
                    + " the only target is the Request-URI (mAddr parameter)");

          // 4. Forward the request statefully:
          requestForwarding.forwardRequest(
              targetURIList, sipProvider, request, serverTransaction, true);

          return;
        }
      }

      /*
       * If the domain of the Request-URI indicates a domain this element
       * is not responsible for, the Request-URI MUST be placed into the
       * target set as the only target, and the element MUST proceed to
       * the task of Request Forwarding (Section 16.6).
       */

      if (requestURI.isSipURI()) {
        SipURI requestSipURI = (SipURI) requestURI;
        if (!configuration.hasDomain(requestSipURI.getHost())) {
          if (ProxyDebug.debug)
            ProxyDebug.println(
                "Proxy, processRequest(),"
                    + " we are not responsible for the domain: Let's check if we have"
                    + " a registration for this domain from another proxy");

          // We have to check if another proxy did not registered
          // to us, in this case we have to use the contacts provided
          // by the registered proxy to create the targets:
          if (registrar.hasDomainRegistered(request)) {
            targetURIList = registrar.getDomainContactsURI(request);
            if (targetURIList != null && !targetURIList.isEmpty()) {
              if (ProxyDebug.debug) {
                ProxyDebug.println(
                    "Proxy, processRequest(), we have"
                        + " a registration for this domain from another proxy");
              }
              // 4. Forward the request statefully:
              requestForwarding.forwardRequest(
                  targetURIList, sipProvider, request, serverTransaction, true);
              return;

            } else {
              targetURIList = new Vector();
              ProxyDebug.println(
                  "Proxy, processRequest(),"
                      + " we are not responsible for the domain: the only target"
                      + " URI is given by the request-URI");
              targetURI = requestURI;
              targetURIList.addElement(targetURI);
            }
          } else {
            ProxyDebug.println(
                "Proxy, processRequest(),"
                    + " we are not responsible for the domain: the only target"
                    + " URI is given by the request-URI");
            targetURI = requestURI;
            targetURIList.addElement(targetURI);
          }

          // 4. Forward the request statelessly:
          requestForwarding.forwardRequest(
              targetURIList, sipProvider, request, serverTransaction, false);

          return;
        } else {
          ProxyDebug.println(
              "Proxy, processRequest(),"
                  + " we are responsible for the domain... Let's find the contact...");
        }
      }

      // we use a SIP registrar:
      if (request.getMethod().equals(Request.REGISTER)) {
        if (ProxyDebug.debug) ProxyDebug.println("Incoming request Register");
        // we call the RegisterProcessing:
        registrar.processRegister(request, sipProvider, serverTransaction);
        // Henrik: let the presenceserver do some processing too
        if (isPresenceServer()) {
          presenceServer.processRegisterRequest(sipProvider, request, serverTransaction);
        }

        return;
      }

      /*
       * If we receive a subscription targeted to a user that is
       * publishing its state here, send to presence server
       */
      if (isPresenceServer() && (request.getMethod().equals(Request.SUBSCRIBE))) {
        ProxyDebug.println("Incoming request Subscribe");

        if (presenceServer.isStateAgent(request)) {
          Request clonedRequest = (Request) request.clone();
          presenceServer.processSubscribeRequest(sipProvider, clonedRequest, serverTransaction);
        } else {
          // Do we know this guy?

          targetURIList = registrar.getContactsURI(request);
          if (targetURIList == null) {
            // If not respond that we dont know him.
            ProxyDebug.println(
                "Proxy: received a Subscribe request to "
                    + " a user in our domain that was not found, "
                    + " responded 404");
            Response response = messageFactory.createResponse(Response.NOT_FOUND, request);
            if (serverTransaction != null) serverTransaction.sendResponse(response);
            else sipProvider.sendResponse(response);
            return;
          } else {
            ProxyDebug.println(
                "Trying to forward subscribe to "
                    + targetURIList.toString()
                    + "\n"
                    + request.toString());
            requestForwarding.forwardRequest(
                targetURIList, sipProvider, request, serverTransaction, false);
          }
        }
        return;
      }

      /** Received a Notify. TOADD: Check if it match active VirtualSubscriptions and update it */
      if (isPresenceServer() && (request.getMethod().equals(Request.NOTIFY))) {
        System.out.println("Incoming request Notify");

        Response response = messageFactory.createResponse(481, request);
        response.setReasonPhrase("Subscription does not exist");
        if (serverTransaction != null) serverTransaction.sendResponse(response);
        else sipProvider.sendResponse(response);
        ProxyDebug.println("Proxy: received a Notify request. Probably wrong, responded 481");
        return;
      }

      if (isPresenceServer() && (request.getMethod().equalsIgnoreCase("PUBLISH"))) {

        System.out.println("Incoming request Publish");

        ProxyDebug.println("Proxy: received a Publish request.");
        Request clonedRequest = (Request) request.clone();

        if (presenceServer.isStateAgent(clonedRequest)) {
          ProxyDebug.println("PresenceServer.isStateAgent");
        } else {
          ProxyDebug.println("PresenceServer is NOT StateAgent");
        }

        if (presenceServer.isStateAgent(clonedRequest)) {
          presenceServer.processPublishRequest(sipProvider, clonedRequest, serverTransaction);
        } else {
          Response response = messageFactory.createResponse(Response.NOT_FOUND, request);
          if (serverTransaction != null) serverTransaction.sendResponse(response);
          else sipProvider.sendResponse(response);
        }
        return;
      }

      // Forward to next hop but dont reply OK right away for the
      // BYE. Bye is end-to-end not hop by hop!
      if (request.getMethod().equals(Request.BYE)) {

        if (serverTransaction == null) {
          if (ProxyDebug.debug) ProxyDebug.println("Proxy, null server transaction for BYE");
          return;
        }

        /* added code */
        CallID call_id = (CallID) request.getHeader(CallID.CALL_ID);
        String call_id_str = call_id.getCallId();
        long end_time = TimeThreadController.Stop(call_id_str);

        To tou = (To) request.getHeader(ToHeader.NAME);
        From fromu = (From) request.getHeader(FromHeader.NAME);

        String FromUser = fromu.getUserAtHostPort();
        String ToUser = tou.getUserAtHostPort();

        StringBuffer sb = new StringBuffer(FromUser);
        int endsAt = sb.indexOf("@");
        String FromUsername = sb.substring(0, endsAt);
        sb = new StringBuffer(ToUser);
        endsAt = sb.indexOf("@");
        String ToUsername = sb.substring(0, endsAt);
        BillStrategyApply bill = new BillStrategyApply(new StandardBillPolicy());
        long start_time = TimeThreadController.getStartTime();
        java.sql.Timestamp s = new java.sql.Timestamp(start_time);
        System.out.println("START TIME POU BIKE :" + s.toString());
        BigDecimal cost = bill.executeStrategy(1, 2, start_time, end_time);
        ProcessBill.updateCallDB(FromUsername, ToUsername, start_time, end_time, cost);

        /* end of added code */

        Dialog d = serverTransaction.getDialog();
        TransactionsMapping transactionsMapping = (TransactionsMapping) d.getApplicationData();
        Dialog peerDialog = (Dialog) transactionsMapping.getPeerDialog(serverTransaction);
        Request clonedRequest = (Request) request.clone();
        FromHeader from = (FromHeader) clonedRequest.getHeader(FromHeader.NAME);
        from.removeParameter("tag");
        ToHeader to = (ToHeader) clonedRequest.getHeader(ToHeader.NAME);
        to.removeParameter("tag");
        ViaHeader via = this.getStackViaHeader();
        clonedRequest.addHeader(via);
        if (peerDialog.getState() != null) {
          ClientTransaction newct = sipProvider.getNewClientTransaction(clonedRequest);
          transactionsMapping.addMapping(serverTransaction, newct);
          peerDialog.sendRequest(newct);
          return;
        } else {
          // the peer dialog is not yet established so bail out.
          // this is a client error - client is sending BYE
          // before dialog establishment.
          if (ProxyDebug.debug) ProxyDebug.println("Proxy, bad dialog state - BYE dropped");
          return;
        }
      }

      /*
       * If the target set for the request has not been predetermined as
       * described above, this implies that the element is responsible for
       * the domain in the Request-URI, and the element MAY use whatever
       * mechanism it desires to determine where to send the request. ...
       * When accessing the location service constructed by a registrar,
       * the Request-URI MUST first be canonicalized as described in
       * Section 10.3 before being used as an index.
       */
      if (requestURI.isSipURI()) {
        SipURI requestSipURI = (SipURI) requestURI;
        Iterator iterator = requestSipURI.getParameterNames();
        if (ProxyDebug.debug)
          ProxyDebug.println("Proxy, processRequest(), we canonicalized" + " the request-URI");
        while (iterator != null && iterator.hasNext()) {
          String name = (String) iterator.next();
          requestSipURI.removeParameter(name);
        }
      }

      if (registrar.hasRegistration(request)) {

        targetURIList = registrar.getContactsURI(request);

        // We fork only INVITE
        if (targetURIList != null
            && targetURIList.size() > 1
            && !request.getMethod().equals("INVITE")) {
          if (ProxyDebug.debug)
            ProxyDebug.println(
                "Proxy, processRequest(), the request "
                    + " to fork is not an INVITE, so we will process"
                    + " it with the first target as the only target.");
          targetURI = (URI) targetURIList.firstElement();
          targetURIList = new Vector();
          targetURIList.addElement(targetURI);
          // 4. Forward the request statefully to the target:
          requestForwarding.forwardRequest(
              targetURIList, sipProvider, request, serverTransaction, true);
          return;
        }

        if (targetURIList != null && !targetURIList.isEmpty()) {
          if (ProxyDebug.debug)
            ProxyDebug.println(
                "Proxy, processRequest(), the target set"
                    + " is the set of the contacts URI from the "
                    + " location service");

          To to = (To) request.getHeader(ToHeader.NAME);
          From from = (From) request.getHeader(FromHeader.NAME);

          String FromUser = from.getUserAtHostPort();
          String ToUser = to.getUserAtHostPort();

          StringBuffer sb = new StringBuffer(FromUser);
          int endsAt = sb.indexOf("@");
          String FromUsername = sb.substring(0, endsAt);
          sb = new StringBuffer(ToUser);
          endsAt = sb.indexOf("@");
          String ToUsername = sb.substring(0, endsAt);

          if (!block.CheckBlock(FromUsername, ToUsername)) {
            Response response =
                messageFactory.createResponse(Response.TEMPORARILY_UNAVAILABLE, request);
            if (serverTransaction != null) serverTransaction.sendResponse(response);
            else sipProvider.sendResponse(response);
            return;
          }
          /*
           * // ECE355 Changes - Aug. 2005. // Call registry service,
           * get response (uri - wsdl). // if response is not null
           * then // do our staff // send to caller decline message by
           * building a decline msg // and attach wsdl uri in the
           * message body // else .. continue the logic below ...
           *
           *
           * // Lets assume that wsdl_string contains the message with
           * all the // service names and uri's for each service in
           * the required format
           *
           * // Query for web services for the receiver of INVITE //
           * Use WebServices class to get services for org
           *
           * String messageBody = "" ; WebServicesQuery wsq = null ;
           * wsq = WebServicesQuery.getInstance();
           *
           * // Get services info for receiver // A receiver is
           * represented as an organization in the Service Registry
           *
           * To to = (To)request.getHeader(ToHeader.NAME); String
           * toAddress = to.getUserAtHostPort();
           *
           * // Remove all characters after the @ sign from To address
           * StringBuffer sb = new StringBuffer(toAddress); int endsAt
           * = sb.indexOf("@"); String orgNamePattern =
           * sb.substring(0, endsAt);
           *
           *
           * Collection serviceInfoColl =
           * wsq.findServicesForOrg(orgNamePattern);
           *
           * // If services are found for this receiver (Org), build
           * DECLINE message and // send to client if (serviceInfoColl
           * != null) { if (serviceInfoColl.size()!= 0 ){
           * System.out.println("Found " + serviceInfoColl.size() +
           * " services for o rg " + orgNamePattern) ; // Build
           * message body for DECLINE message with Service Info
           * messageBody = serviceInfoColl.size()+ " -- " ;
           *
           * Iterator servIter = serviceInfoColl.iterator(); while
           * (servIter.hasNext()) { ServiceInfo servInfo =
           * (ServiceInfo)servIter.next(); messageBody = messageBody +
           * servInfo.getDescription()+ " " + servInfo.getWsdluri() +
           * " " + servInfo.getEndPoint()+ " -- ";
           *
           *
           * System.out.println("Name: " + servInfo.getName()) ;
           * System.out.println("Providing Organization: " +
           * servInfo.getProvidingOrganization()) ;
           * System.out.println("Description: " +
           * servInfo.getDescription()) ;
           * System.out.println("Service End Point " +
           * servInfo.getEndPoint()) ; System.out.println("wsdl wri "
           * + servInfo.getWsdluri()) ;
           * System.out.println("---------------------------------");
           *
           *
           *
           * }
           *
           * System.out.println("ServiceInfo - Message Body  " +
           * messageBody) ;
           *
           * // Build and send DECLINE message with web service info
           *
           * ContentTypeHeader contentTypeHeader = new ContentType(
           * "text", "plain");
           *
           * Response response = messageFactory.createResponse(
           * Response.DECLINE, request, contentTypeHeader,
           * messageBody);
           *
           *
           *
           * if (serverTransaction != null)
           * serverTransaction.sendResponse(response); else
           * sipProvider.sendResponse(response); return; } else
           * System.out.println("There are no services for org " +
           * orgNamePattern) ;
           *
           * }
           *
           * // End of ECE355 change
           */

          // 4. Forward the request statefully to each target Section
          // 16.6.:
          requestForwarding.forwardRequest(
              targetURIList, sipProvider, request, serverTransaction, true);

          return;
        } else {
          // Let's continue and try the default hop.
        }
      }

      // The registrar cannot help to decide the targets, so let's use
      // our router: the default hop!
      ProxyDebug.println(
          "Proxy, processRequest(), the registrar cannot help"
              + " to decide the targets, so let's use our router: the default hop");
      Router router = sipStack.getRouter();
      if (router != null) {
        ProxyHop hop = (ProxyHop) router.getOutboundProxy();
        if (hop != null) {
          if (ProxyDebug.debug)
            ProxyDebug.println(
                "Proxy, processRequest(), the target set" + " is the defaut hop: outbound proxy");

          // Bug fix contributed by Joe Provino
          String user = null;

          if (requestURI.isSipURI()) {
            SipURI requestSipURI = (SipURI) requestURI;
            user = requestSipURI.getUser();
          }

          SipURI hopURI = addressFactory.createSipURI(user, hop.getHost());
          hopURI.setTransportParam(hop.getTransport());
          hopURI.setPort(hop.getPort());
          targetURI = hopURI;
          targetURIList.addElement(targetURI);

          // 4. Forward the request statelessly to each target Section
          // 16.6.:
          requestForwarding.forwardRequest(
              targetURIList, sipProvider, request, serverTransaction, false);

          return;
        }
      }

      /*
       * If the target set remains empty after applying all of the above,
       * the proxy MUST return an error response, which SHOULD be the 480
       * (Temporarily Unavailable) response.
       */
      Response response = messageFactory.createResponse(Response.TEMPORARILY_UNAVAILABLE, request);
      if (serverTransaction != null) serverTransaction.sendResponse(response);
      else sipProvider.sendResponse(response);

      if (ProxyDebug.debug)
        ProxyDebug.println(
            "Proxy, processRequest(), unable to set "
                + " the targets, 480 (Temporarily Unavailable) replied:\n"
                + response.toString());

    } catch (Exception ex) {
      try {
        if (ProxyDebug.debug) {
          ProxyDebug.println("Proxy, processRequest(), internal error, " + "exception raised:");
          ProxyDebug.logException(ex);
          ex.printStackTrace();
        }

        // This is an internal error:
        // Let's return a 500 SERVER_INTERNAL_ERROR
        Response response = messageFactory.createResponse(Response.SERVER_INTERNAL_ERROR, request);
        if (serverTransaction != null) serverTransaction.sendResponse(response);
        else sipProvider.sendResponse(response);

        if (ProxyDebug.debug)
          ProxyDebug.println(
              "Proxy, processRequest(),"
                  + " 500 SERVER_INTERNAL_ERROR replied:\n"
                  + response.toString());
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }
  public void processMessage(Request request, ServerTransaction serverTransaction) {
    try {
      SipProvider sipProvider = imUA.getSipProvider();
      MessageFactory messageFactory = imUA.getMessageFactory();
      HeaderFactory headerFactory = imUA.getHeaderFactory();
      AddressFactory addressFactory = imUA.getAddressFactory();

      InstantMessagingGUI instantMessagingGUI = imUA.getInstantMessagingGUI();
      ListenerInstantMessaging listenerInstantMessaging =
          instantMessagingGUI.getListenerInstantMessaging();
      ChatSessionManager chatSessionManager = listenerInstantMessaging.getChatSessionManager();
      ChatSession chatSession = null;
      String fromURL = IMUtilities.getKey(request, "From");
      if (chatSessionManager.hasAlreadyChatSession(fromURL))
        chatSession = chatSessionManager.getChatSession(fromURL);
      else chatSession = chatSessionManager.createChatSession(fromURL);

      DebugIM.println("IMMessageProcessing, processMEssage(), ChatSession:" + chatSession);
      DebugIM.println("Processing MESSAGE in progress...");

      // Send an OK
      Response response = messageFactory.createResponse(Response.OK, request);
      // Contact header:
      SipURI sipURI = addressFactory.createSipURI(null, imUA.getIMAddress());
      sipURI.setPort(imUA.getIMPort());
      sipURI.setTransportParam(imUA.getIMProtocol());
      Address contactAddress = addressFactory.createAddress(sipURI);
      ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
      response.setHeader(contactHeader);
      ToHeader toHeader = (ToHeader) response.getHeader(ToHeader.NAME);
      if (toHeader.getTag() == null) {
        // It is the first message without a TO tag
        toHeader.setTag(new Integer((int) (Math.random() * 10000)).toString());
      }

      if (chatSession.isEstablishedSession()) {
        DebugIM.println("The Session already exists");
        serverTransaction.sendResponse(response);
        DebugIM.println("OK replied to the MESSAGE:\n" + response.toString());
      } else {
        DebugIM.println("The Session does not exists yet. ");
        serverTransaction.sendResponse(response);
        DebugIM.println("OK replied to the MESSAGE:\n" + response.toString());

        Dialog dialog = serverTransaction.getDialog();
        if (dialog == null) {
          DebugIM.println("ERROR, IMProcessing, processMessage(), the dialog is null");
          return;
        }
        // We need to store the dialog:
        chatSession.setDialog(dialog);
        chatSession.setEstablishedSession(true);
        DebugIM.println("The DIALOG object has been stored in the ChatSession");
      }

      Object content = request.getContent();
      String text = null;
      if (content instanceof String) text = (String) content;
      else if (content instanceof byte[]) {
        text = new String((byte[]) content);
      } else {
      }
      if (text != null) {
        chatSession.displayRemoteText(text);
      }
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }