예제 #1
0
  /**
   * Shows a warning message to the user when message delivery has failed.
   *
   * @param evt the event containing details on the message delivery failure
   */
  public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) {
    logger.error(evt.getReason());

    String errorMsg = null;

    Message sourceMessage = (Message) evt.getSource();

    Contact sourceContact = evt.getDestinationContact();

    MetaContact metaContact =
        GuiActivator.getContactListService().findMetaContactByContact(sourceContact);

    if (evt.getErrorCode() == MessageDeliveryFailedEvent.OFFLINE_MESSAGES_NOT_SUPPORTED) {
      errorMsg =
          GuiActivator.getResources()
              .getI18NString(
                  "service.gui.MSG_DELIVERY_NOT_SUPPORTED",
                  new String[] {sourceContact.getDisplayName()});
    } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.NETWORK_FAILURE) {
      errorMsg = GuiActivator.getResources().getI18NString("service.gui.MSG_NOT_DELIVERED");
    } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.PROVIDER_NOT_REGISTERED) {
      errorMsg =
          GuiActivator.getResources().getI18NString("service.gui.MSG_SEND_CONNECTION_PROBLEM");
    } else if (evt.getErrorCode() == MessageDeliveryFailedEvent.INTERNAL_ERROR) {
      errorMsg =
          GuiActivator.getResources().getI18NString("service.gui.MSG_DELIVERY_INTERNAL_ERROR");
    } else {
      errorMsg = GuiActivator.getResources().getI18NString("service.gui.MSG_DELIVERY_ERROR");
    }

    String reason = evt.getReason();
    if (reason != null)
      errorMsg +=
          " "
              + GuiActivator.getResources()
                  .getI18NString("service.gui.ERROR_WAS", new String[] {reason});

    ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, sourceContact);

    chatPanel.addMessage(
        sourceContact.getAddress(),
        metaContact.getDisplayName(),
        new Date(),
        Chat.OUTGOING_MESSAGE,
        sourceMessage.getContent(),
        sourceMessage.getContentType(),
        sourceMessage.getMessageUID(),
        evt.getCorrectedMessageUID());

    chatPanel.addErrorMessage(metaContact.getDisplayName(), errorMsg);

    chatWindowManager.openChat(chatPanel, false);
  }
예제 #2
0
  /**
   * When a sent message is delivered shows it in the chat conversation panel.
   *
   * @param evt the event containing details on the message delivery
   */
  public void messageDelivered(MessageDeliveredEvent evt) {
    Contact contact = evt.getDestinationContact();
    MetaContact metaContact =
        GuiActivator.getContactListService().findMetaContactByContact(contact);

    if (logger.isTraceEnabled())
      logger.trace("MESSAGE DELIVERED to contact: " + contact.getAddress());

    ChatPanel chatPanel = chatWindowManager.getContactChat(metaContact, false);

    if (chatPanel != null) {
      Message msg = evt.getSourceMessage();
      ProtocolProviderService protocolProvider = contact.getProtocolProvider();

      if (logger.isTraceEnabled())
        logger.trace(
            "MESSAGE DELIVERED: process message to chat for contact: "
                + contact.getAddress()
                + " MESSAGE: "
                + msg.getContent());

      chatPanel.addMessage(
          this.mainFrame.getAccountAddress(protocolProvider),
          this.mainFrame.getAccountDisplayName(protocolProvider),
          evt.getTimestamp(),
          Chat.OUTGOING_MESSAGE,
          msg.getContent(),
          msg.getContentType(),
          msg.getMessageUID(),
          evt.getCorrectedMessageUID());

      if (evt.isSmsMessage() && !ConfigurationUtils.isSmsNotifyTextDisabled()) {
        chatPanel.addMessage(
            contact.getDisplayName(),
            new Date(),
            Chat.ACTION_MESSAGE,
            GuiActivator.getResources().getI18NString("service.gui.SMS_SUCCESSFULLY_SENT"),
            "text");
      }
    }
  }
  /**
   * Sends the <tt>message</tt> to the destination indicated by the <tt>to</tt> contact.
   *
   * @param to the <tt>Contact</tt> to send <tt>message</tt> to
   * @param message the <tt>Message</tt> to send.
   * @throws IllegalStateException if the underlying ICQ stack is not registered and initialized.
   * @throws IllegalArgumentException if <tt>to</tt> is not an instance belonging to the underlying
   *     implementation.
   */
  public void sendInstantMessage(Contact to, Message message)
      throws IllegalStateException, IllegalArgumentException {
    if (!(to instanceof ContactDictImpl)) {
      throw new IllegalArgumentException("The specified contact is not a Dict contact." + to);
    }

    // Remove all html tags from the message
    message = createMessage(Html2Text.extractText(message.getContent()));

    // Display the queried word
    fireMessageDelivered(message, to);

    this.submitDictQuery((ContactDictImpl) to, message);
  }
  /**
   * Create, execute and display a query to a dictionary (ContactDictImpl)
   *
   * @param dictContact the contact containing the database name
   * @param message the message containing the word
   */
  private void submitDictQuery(ContactDictImpl dictContact, Message message) {
    Message msg = this.createMessage("");

    String database = dictContact.getContactID();
    DictConnection conn = this.parentProvider.getConnection();
    boolean doMatch = false;

    String word;

    // Formatting the query message, if the word as one or more spaces we
    // put it between quotes to prevent errors
    word = message.getContent().replace("\"", "").trim();
    if (word.indexOf(' ') > 0) {
      word = "\"" + word + "\"";
    }

    // Try to get the definition of the work
    try {
      List<Definition> definitions = conn.define(database, word);
      msg = this.createMessage(retrieveDefine(definitions, word));
    } catch (DictException dx) {
      if (dx.getErrorCode()
          == DictReturnCode.NO_MATCH) { // No word found, we are going to try the match command
        doMatch = true;
      } else { // Otherwise we display the error returned by the server
        msg = this.createMessage(manageException(dx, database));
      }
    }

    if (doMatch) {
      // Trying the match command
      try {
        List<MatchWord> matchWords = conn.match(database, word, this.accountID.getStrategy());
        msg = this.createMessage(retrieveMatch(matchWords, word));
      } catch (DictException dx) {
        msg = this.createMessage(manageException(dx, database));
      }
    }

    // Send message
    fireMessageReceived(msg, dictContact);
  }
예제 #5
0
  /** The diagnostics code itself. */
  public void run() {
    logger.debug("Started a diag kit for entry: " + addressEntry);

    // implements the algorithm from AssigningAddressPreferences.png

    setDiagnosticsStatus(this.DIAGNOSTICS_STATUS_DISOVERING_CONFIG);

    InetAddress address = addressEntry.getInetAddress();

    // is this an ipv6 address
    if (addressEntry.isIPv6()) {
      if (addressEntry.isLinkLocal()) {
        addressEntry.setAddressPreference(ADDR_PREF_LOCAL_IPV6);
        setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
        return;
      }

      if (addressEntry.is6to4()) {
        // right now we don't support these. we should though ... one day
        addressEntry.setAddressPreference(AddressPreference.MIN);
        setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
        return;
      }

      // if we get here then we are a globally routable ipv6 addr
      addressEntry.setAddressPreference(ADDR_PREF_GLOBAL_IPV6);
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_COMPLETED);
      // should do some connectivity testing here and proceed with firewall
      // discovery but since stun4j does not support ipv6 yet, this too
      // will happen another day.
      return;
    }

    // from now on we're only dealing with IPv4
    if (addressEntry.isIPv4LinkLocalAutoconf()) {
      // not sure whether these are used for anything.
      addressEntry.setAddressPreference(AddressPreference.MIN);
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      return;
    }

    // first try and see what we can infer from just looking at the
    // address
    if (addressEntry.isLinkLocalIPv4Address()) {
      addressEntry.setAddressPreference(ADDR_PREF_PRIVATE_IPV4);
    } else {
      // public address
      addressEntry.setAddressPreference(ADDR_PREF_GLOBAL_IPV4);
    }

    if (!useStun) {
      // if we're configured not to run stun - we're done.
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      return;
    }

    // start stunning
    for (int i = 0; i < bindRetries; i++) {
      StunAddress localStunAddress = new StunAddress(address, 1024 + (int) (Math.random() * 64512));
      try {

        stunClient = new StunClient(localStunAddress);
        stunClient.start();
        logger.debug("Successfully started StunClient for  " + localStunAddress + ".");
        break;
      } catch (StunException ex) {
        if (ex.getCause() instanceof SocketException && i < bindRetries) {
          logger.debug("Failed to bind to " + localStunAddress + ". Retrying ...");
          logger.debug("Exception was ", ex);
          continue;
        }
        logger.error(
            "Failed to start a stun client for address entry ["
                + addressEntry.toString()
                + "]:"
                + localStunAddress.getPort()
                + ". Ceasing attempts",
            ex);
        setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
        return;
      }
    }
    // De Stun Test I
    StunMessageEvent event = null;
    try {
      event = stunClient.doStunTestI(primaryStunServerAddress);
    } catch (StunException ex) {
      logger.error("Failed to perform STUN Test I for address entry" + addressEntry.toString(), ex);
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      return;
    }

    if (event == null) {
      // didn't get a response - we either don't have connectivity or the
      // server is down
      /** @todo if possible try another stun server here. we should support multiple stun servers */
      logger.debug("There seems to be no inet connectivity for " + addressEntry);
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      logger.debug("stun test 1 failed");
      return;
    }

    // the moment of the truth - are we behind a NAT?
    boolean isPublic;
    Message stunResponse = event.getMessage();

    Attribute mappedAttr = stunResponse.getAttribute(Attribute.MAPPED_ADDRESS);

    StunAddress mappedAddrFromTestI = ((MappedAddressAttribute) mappedAttr).getAddress();
    Attribute changedAddressAttributeFromTestI =
        stunResponse.getAttribute(Attribute.CHANGED_ADDRESS);
    StunAddress secondaryStunServerAddress =
        ((ChangedAddressAttribute) changedAddressAttributeFromTestI).getAddress();

    /**
     * @todo verify whether the stun server returned the same address for the primary and secondary
     *     server and act accordingly
     */
    if (mappedAddrFromTestI == null) {
      logger.error(
          "Stun Server did not return a mapped address for entry " + addressEntry.toString());
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      return;
    }

    if (mappedAddrFromTestI.equals(event.getSourceAccessPoint().getAddress())) {
      isPublic = true;
    } else {
      isPublic = false;
    }

    // do STUN Test II
    try {
      event = stunClient.doStunTestII(primaryStunServerAddress);
    } catch (StunException ex) {
      logger.error(
          "Failed to perform STUN Test II for address entry" + addressEntry.toString(), ex);
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      logger.debug("stun test 2 failed");
      return;
    }

    if (event != null) {
      logger.error("Secondary STUN server is down" + addressEntry.toString());
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      return;
    }

    // might mean that either the secondary stun server is down
    // or that we are behind a restrictive firewall. Let's find out
    // which.
    try {
      event = stunClient.doStunTestI(secondaryStunServerAddress);
      logger.debug("stun test 1 succeeded with s server 2");
    } catch (StunException ex) {
      logger.error("Failed to perform STUN Test I for address entry" + addressEntry.toString(), ex);
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      return;
    }

    if (event == null) {
      // secondary stun server is down
      logger.error("Secondary STUN server is down" + addressEntry.toString());
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      return;
    }

    // we are at least behind a port restricted nat

    stunResponse = event.getMessage();
    mappedAttr = stunResponse.getAttribute(Attribute.MAPPED_ADDRESS);
    StunAddress mappedAddrFromSecServer = ((MappedAddressAttribute) mappedAttr).getAddress();

    if (!mappedAddrFromTestI.equals(mappedAddrFromSecServer)) {
      // secondary stun server is down
      logger.debug("We are behind a symmetric nat" + addressEntry.toString());
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      return;
    }

    // now let's run test III so that we could guess whether or not we're
    // behind a port restricted nat/fw or simply a restricted one.
    try {
      event = stunClient.doStunTestIII(primaryStunServerAddress);
      logger.debug("stun test 3 succeeded with s server 1");
    } catch (StunException ex) {
      logger.error(
          "Failed to perform STUN Test III for address entry" + addressEntry.toString(), ex);
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      return;
    }

    if (event == null) {
      logger.debug("We are behind a port restricted NAT or fw" + addressEntry.toString());
      setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
      stunClient.shutDown();
      return;
    }

    logger.debug("We are behind a restricted NAT or fw" + addressEntry.toString());
    setDiagnosticsStatus(DIAGNOSTICS_STATUS_TERMINATED);
    stunClient.shutDown();
  }
예제 #6
0
  /**
   * When a message is received determines whether to open a new chat window or chat window tab, or
   * to indicate that a message is received from a contact which already has an open chat. When the
   * chat is found checks if in mode "Auto popup enabled" and if this is the case shows the message
   * in the appropriate chat panel.
   *
   * @param protocolContact the source contact of the event
   * @param contactResource the resource from which the contact is writing
   * @param metaContact the metacontact containing <tt>protocolContact</tt>
   * @param message the message to deliver
   * @param eventType the event type
   * @param timestamp the timestamp of the event
   * @param correctedMessageUID the identifier of the corrected message
   * @param isPrivateMessaging if <tt>true</tt> the message is received from private messaging
   *     contact.
   * @param privateContactRoom the chat room associated with the private messaging contact.
   */
  private void messageReceived(
      final Contact protocolContact,
      final ContactResource contactResource,
      final MetaContact metaContact,
      final Message message,
      final int eventType,
      final Date timestamp,
      final String correctedMessageUID,
      final boolean isPrivateMessaging,
      final ChatRoom privateContactRoom) {
    if (!SwingUtilities.isEventDispatchThread()) {
      SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              messageReceived(
                  protocolContact,
                  contactResource,
                  metaContact,
                  message,
                  eventType,
                  timestamp,
                  correctedMessageUID,
                  isPrivateMessaging,
                  privateContactRoom);
            }
          });
      return;
    }

    // Obtain the corresponding chat panel.
    final ChatPanel chatPanel =
        chatWindowManager.getContactChat(
            metaContact, protocolContact, contactResource, message.getMessageUID());

    // Show an envelope on the sender contact in the contact list and
    // in the systray.
    if (!chatPanel.isChatFocused()) contactList.setActiveContact(metaContact, true);

    // Distinguish the message type, depending on the type of event that
    // we have received.
    String messageType = null;

    if (eventType == MessageReceivedEvent.CONVERSATION_MESSAGE_RECEIVED) {
      messageType = Chat.INCOMING_MESSAGE;
    } else if (eventType == MessageReceivedEvent.SYSTEM_MESSAGE_RECEIVED) {
      messageType = Chat.SYSTEM_MESSAGE;
    } else if (eventType == MessageReceivedEvent.SMS_MESSAGE_RECEIVED) {
      messageType = Chat.SMS_MESSAGE;
    }

    String contactAddress =
        (contactResource != null)
            ? protocolContact.getAddress() + " (" + contactResource.getResourceName() + ")"
            : protocolContact.getAddress();

    chatPanel.addMessage(
        contactAddress,
        protocolContact.getDisplayName(),
        timestamp,
        messageType,
        message.getContent(),
        message.getContentType(),
        message.getMessageUID(),
        correctedMessageUID);

    String resourceName = (contactResource != null) ? contactResource.getResourceName() : null;

    if (isPrivateMessaging) {
      chatWindowManager.openPrivateChatForChatRoomMember(privateContactRoom, protocolContact);
    } else {
      chatWindowManager.openChat(chatPanel, false);
    }

    ChatTransport chatTransport =
        chatPanel.getChatSession().findChatTransportForDescriptor(protocolContact, resourceName);

    chatPanel.setSelectedChatTransport(chatTransport, true);
  }