/*************************************************************************** * Copyright 2006-2016 by Christian Ihle * * contact@kouchat.net * * * * This file is part of KouChat. * * * * KouChat is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version. * * * * KouChat is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with KouChat. * * If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ package net.usikkert.kouchat.net; import static net.usikkert.kouchat.net.NetworkMessageType.*; import net.usikkert.kouchat.misc.CommandException; import net.usikkert.kouchat.misc.Topic; import net.usikkert.kouchat.misc.User; import net.usikkert.kouchat.settings.Settings; import net.usikkert.kouchat.util.Validate; /** * This class gives access to sending the different kinds of network messages * that this application supports. Both multicast, and normal udp. * * @author Christian Ihle */ public class NetworkMessages { /** The network service used for sending the actual messages. */ private final NetworkService networkService; /** The application user. */ private final User me; /** Settings. */ private final Settings settings; /** * Constructor. * * @param networkService The network service used for sending the actual messages. * @param settings The settings to use. */ public NetworkMessages(final NetworkService networkService, final Settings settings) { Validate.notNull(networkService, "Network service can not be null"); Validate.notNull(settings, "Settings can not be null"); this.networkService = networkService; this.settings = settings; me = settings.getMe(); } /** * Sends a message notifying other clients that this client is still alive. * * <p>Note: the network will be checked if this fails!</p> */ public void sendIdleMessage() { final String msg = createMessage(IDLE); final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); } } /** * Sends a message to change the topic. * * <p>Note: the network will be checked if this fails!</p> * * @param topic The new topic to send. */ public void sendTopicChangeMessage(final Topic topic) { final String msg = createTopicMessage(topic); final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); } } /** * Sends a message with the current topic. * * @param topic The current topic to send. */ public void sendTopicRequestedMessage(final Topic topic) { final String msg = createTopicMessage(topic); networkService.sendMulticastMsg(msg); } /** * Sends a message to set the user as away, including the away message. * * <p>Note: the network will be checked if this fails!</p> * * @param awayMsg The away message to set. */ public void sendAwayMessage(final String awayMsg) { final String msg = createMessage(AWAY) + awayMsg; final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); } } /** * Sends a message to set the user as back from away. * * <p>Note: the network will be checked if this fails!</p> */ public void sendBackMessage() { final String msg = createMessage(BACK); final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); } } /** * Sends a normal chat message, that is part of the main chat. * * <p>Note: the network will be checked, and the user notified if this fails!</p> * * @param chatMsg The message for the main chat. * @throws CommandException If the message was not sent successfully. */ public void sendChatMessage(final String chatMsg) throws CommandException { final String msg = createMessage(MSG) + "[" + settings.getOwnColor() + "]" + chatMsg; final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); notifyUser("Failed to send message: " + chatMsg); } } /** * Sends a message to log this client on the network. */ public void sendLogonMessage() { final String msg = createMessage(LOGON); networkService.sendMulticastMsg(msg); } /** * Sends a message to log this client off the network. */ public void sendLogoffMessage() { final String msg = createMessage(LOGOFF); networkService.sendMulticastMsg(msg); } /** * Sends a message asking the other clients to identify themselves. */ public void sendExposeMessage() { final String msg = createMessage(EXPOSE); networkService.sendMulticastMsg(msg); } /** * Sends a message to identify this client. */ public void sendExposingMessage() { final String msg = createMessage(EXPOSING) + me.getAwayMsg(); networkService.sendMulticastMsg(msg); } /** * Sends a message to ask for the current topic. */ public void sendGetTopicMessage() { final String msg = createMessage(GETTOPIC); networkService.sendMulticastMsg(msg); } /** * Sends a message to notify that the user is writing. */ public void sendWritingMessage() { final String msg = createMessage(WRITING); networkService.sendMulticastMsg(msg); } /** * Sends a message to notify that the user has stopped writing. */ public void sendStoppedWritingMessage() { final String msg = createMessage(STOPPEDWRITING); networkService.sendMulticastMsg(msg); } /** * Sends a message to change the nick name of the user. * * <p>Note: the network will be checked if this fails!</p> * * @param newNick The new nick to send. */ public void sendNickMessage(final String newNick) { final String msg = createMessage(NICK, newNick); final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); } } /** * Sends a message to inform that another user has logged on with * the same nick name as this user. * * @param crashNick The nick name that is already in use by the user. */ public void sendNickCrashMessage(final String crashNick) { final String msg = createMessage(NICKCRASH) + crashNick; networkService.sendMulticastMsg(msg); } /** * Sends a message to notify the file sender that you aborted the file transfer. * * @param user The user sending a file. * @param fileHash The unique hash code of the file. * @param fileName The name of the file. */ public void sendFileAbort(final User user, final int fileHash, final String fileName) { final String msg = createMessage(SENDFILEABORT) + "(" + user.getCode() + ")" + "{" + fileHash + "}" + fileName; final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); } } /** * Sends a message to notify the file sender that you * accepted the file transfer. * * <p>Note: the network will be checked, and the user notified if this fails!</p> * * @param user The user sending a file. * @param port The port the file sender can connect to on this client * to start the file transfer. * @param fileHash The unique hash code of the file. * @param fileName The name of the file. * @throws CommandException If the message was not sent successfully. */ public void sendFileAccept(final User user, final int port, final int fileHash, final String fileName) throws CommandException { final String msg = createMessage(SENDFILEACCEPT) + "(" + user.getCode() + ")" + "[" + port + "]" + "{" + fileHash + "}" + fileName; final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); notifyUser("Failed to accept file transfer from " + user.getNick() + ": " + fileName); } } /** * Sends a message to notify another user that you want to send a file. * * <p>Note: the network will be checked, and the user notified if this fails!</p> * * @param user The user asked to receive a file. * @param file The file to send. * @throws CommandException If the message was not sent successfully. */ public void sendFile(final User user, final FileToSend file) throws CommandException { final String msg = createMessage(SENDFILE) + "(" + user.getCode() + ")" + "[" + file.length() + "]" + "{" + file.hashCode() + "}" + file.getName(); final boolean sent = networkService.sendMulticastMsg(msg); if (!sent) { checkNetwork(); notifyUser("Failed to send file to " + user.getNick() + ": " + file.getName()); } } /** * Sends a message with extra client information: * * <ul> * <li>Name of the client.</li> * <li>Client uptime.</li> * <li>Operating system.</li> * <li>Port to connect to for private chat.</li> * </ul> */ public void sendClient() { final String msg = createMessage(CLIENT) + "(" + me.getClient() + ")" + "[" + (System.currentTimeMillis() - me.getLogonTime()) + "]" + "{" + me.getOperatingSystem() + "}" + "<" + me.getPrivateChatPort() + ">"; networkService.sendMulticastMsg(msg); } /** * Sends a private message to a user. * * <p>Note: the network will be checked, and the user notified if this fails!</p> * * @param privMsg The private message to send. * @param user The user to send the message to. * @throws CommandException If the message was not sent successfully. */ public void sendPrivateMessage(final String privMsg, final User user) throws CommandException { final String msg = createMessage(PRIVMSG) + "(" + user.getCode() + ")" + "[" + settings.getOwnColor() + "]" + privMsg; final boolean sent = networkService.sendUDPMsg(msg, user.getIpAddress(), user.getPrivateChatPort()); if (!sent) { checkNetwork(); notifyUser("Failed to send private message to " + user.getNick() + ": " + privMsg); } } /** * Creates the standard part of all messages, with the specified type * as the message type. * * @param type The message type. * @return The standard part of the message. */ private String createMessage(final String type) { return createMessage(type, me.getNick()); } /** * Creates the standard part of all messages, with the specified type * as the message type, and a specified nick name. * * @param type The message type. * @param nick The nick name to use in the message. * @return The standard part of the message. */ private String createMessage(final String type, final String nick) { return me.getCode() + "!" + type + "#" + nick + ":"; } /** * Creates a new message for sending the topic. * * @param topic The topic to use in the message. * @return The new message. */ private String createTopicMessage(final Topic topic) { return createMessage(TOPIC) + "(" + topic.getNick() + ")" + "[" + topic.getTime() + "]" + topic.getTopic(); } /** * Informs the user that the message could not be delivered. * * @param infoMsg The message to give the user. * @throws CommandException The exception returned with the message. */ private void notifyUser(final String infoMsg) throws CommandException { throw new CommandException(infoMsg); } /** * Asks the network service to check the network status. */ private void checkNetwork() { networkService.checkNetwork(); } }