X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Firc%2FConnection.java;h=4d601fd9aa2e60c69827b784c7170f4fda36c2cb;hb=d1ec38be6ca58fb782aeb413c1b238b23c02c00a;hp=b1ca64ac6182a5c422096b7bf11444a5b3c032f0;hpb=7b59d18363cde726bd18d80571054442671d1a34;p=xudocci.git diff --git a/src/main/java/net/pterodactylus/irc/Connection.java b/src/main/java/net/pterodactylus/irc/Connection.java index b1ca64a..4d601fd 100644 --- a/src/main/java/net/pterodactylus/irc/Connection.java +++ b/src/main/java/net/pterodactylus/irc/Connection.java @@ -18,6 +18,7 @@ package net.pterodactylus.irc; import static com.google.common.base.Preconditions.checkState; +import static java.util.Arrays.asList; import static java.util.concurrent.TimeUnit.SECONDS; import java.io.BufferedReader; @@ -35,10 +36,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + import javax.net.SocketFactory; +import net.pterodactylus.irc.connection.ChannelNotJoinedHandler; +import net.pterodactylus.irc.connection.ConnectionEstablishHandler; +import net.pterodactylus.irc.connection.Handler; import net.pterodactylus.irc.event.ChannelJoined; import net.pterodactylus.irc.event.ChannelLeft; import net.pterodactylus.irc.event.ChannelMessageReceived; @@ -53,12 +58,14 @@ import net.pterodactylus.irc.event.ConnectionEstablished; import net.pterodactylus.irc.event.ConnectionFailed; import net.pterodactylus.irc.event.DccAcceptReceived; import net.pterodactylus.irc.event.DccSendReceived; +import net.pterodactylus.irc.event.KickedFromChannel; import net.pterodactylus.irc.event.MotdReceived; import net.pterodactylus.irc.event.NicknameChanged; import net.pterodactylus.irc.event.NicknameInUseReceived; import net.pterodactylus.irc.event.NoNicknameGivenReceived; import net.pterodactylus.irc.event.PrivateMessageReceived; import net.pterodactylus.irc.event.PrivateNoticeReceived; +import net.pterodactylus.irc.event.ReplyReceived; import net.pterodactylus.irc.event.UnknownReplyReceived; import net.pterodactylus.irc.util.RandomNickname; import net.pterodactylus.xdcc.util.io.BandwidthCountingInputStream; @@ -68,11 +75,13 @@ import com.google.common.base.Optional; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; import com.google.common.io.Closeables; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; import com.google.common.util.concurrent.AbstractExecutionThreadService; import com.google.common.util.concurrent.Service; +import org.apache.log4j.Logger; /** * A connection to an IRC server. @@ -121,7 +130,7 @@ public class Connection extends AbstractExecutionThreadService implements Servic private ConnectionHandler connectionHandler; /** Whether the connection has already been established. */ - private boolean established; + private final AtomicBoolean established = new AtomicBoolean(); /** * Creates a new connection. @@ -171,7 +180,7 @@ public class Connection extends AbstractExecutionThreadService implements Servic * false} otherwise */ public boolean established() { - return established; + return established.get(); } /** @@ -324,7 +333,9 @@ public class Connection extends AbstractExecutionThreadService implements Servic * if an I/O error occurs */ public void close() throws IOException { - connectionHandler.close(); + if (connectionHandler != null) { + connectionHandler.close(); + } } // @@ -343,6 +354,7 @@ public class Connection extends AbstractExecutionThreadService implements Servic /* connect to remote socket. */ try { Socket socket = socketFactory.createSocket(hostname, port); + socket.setSoTimeout((int) TimeUnit.MINUTES.toMillis(3)); connectionHandler = new ConnectionHandler(socket.getInputStream(), socket.getOutputStream()); /* register connection. */ @@ -358,11 +370,10 @@ public class Connection extends AbstractExecutionThreadService implements Servic return; } + eventBus.register(this); /* now read replies and react. */ try { /* some status variables. */ - int oldConnectionStatus = 0; - int connectionStatus = 0; boolean connected = true; StringBuilder motd = new StringBuilder(); Set nicks = Sets.newHashSet(); @@ -371,12 +382,25 @@ public class Connection extends AbstractExecutionThreadService implements Servic Map nickPrefixes = Maps.newHashMap(); Set channelTypes = Sets.newHashSet(); + List handlers = asList( + new ConnectionEstablishHandler(eventBus, this), + new ChannelNotJoinedHandler(eventBus, this) + ); + while (connected) { Reply reply = connectionHandler.readReply(); - logger.finest(String.format("<< %s", reply)); + eventBus.post(new ReplyReceived(this, reply)); + logger.trace(String.format("<< %s", reply)); String command = reply.command(); List parameters = reply.parameters(); + for (Handler handler : handlers) { + if (handler.willHandle(reply)) { + handler.handleReply(reply); + break; + } + } + /* most common events. */ if (command.equalsIgnoreCase("PRIVMSG")) { String recipient = parameters.get(0); @@ -406,7 +430,7 @@ public class Connection extends AbstractExecutionThreadService implements Servic } else if (command.equals("431")) { eventBus.post(new NoNicknameGivenReceived(this, reply)); } else if (command.equals("433")) { - if (connectionStatus == 0) { + if (!established.get()) { nickname = nicknameChooser.getNickname(); connectionHandler.sendCommand("NICK", nickname); } else { @@ -440,28 +464,10 @@ public class Connection extends AbstractExecutionThreadService implements Servic } else if (command.equalsIgnoreCase("QUIT")) { eventBus.post(new ClientQuit(this, reply.source().get(), parameters.get(0))); - /* common channel join errors. */ - } else if (command.equals("474")) { - eventBus.post(new ChannelNotJoined(this, parameters.get(1), Reason.banned)); - } else if (command.equals("473")) { - eventBus.post(new ChannelNotJoined(this, parameters.get(1), Reason.inviteOnly)); - } else if (command.equals("475")) { - eventBus.post(new ChannelNotJoined(this, parameters.get(1), Reason.badChannelKey)); - /* basic connection housekeeping. */ } else if (command.equalsIgnoreCase("PING")) { connectionHandler.sendCommand("PONG", getOptional(parameters, 0), getOptional(parameters, 1)); - /* replies 001-004 don’t hold information but they have to be sent on a successful connection. */ - } else if (command.equals("001")) { - connectionStatus |= 0x01; - } else if (command.equals("002")) { - connectionStatus |= 0x02; - } else if (command.equals("003")) { - connectionStatus |= 0x04; - } else if (command.equals("004")) { - connectionStatus |= 0x08; - /* 005 originally was a bounce message, now used to transmit useful information about the server. */ } else if (command.equals("005")) { for (String parameter : parameters) { @@ -474,13 +480,13 @@ public class Connection extends AbstractExecutionThreadService implements Servic char modeSymbol = parameter.charAt(closeParen + modeCharacterIndex); nickPrefixes.put(String.valueOf(modeSymbol), String.valueOf(modeCharacter)); } - logger.fine(String.format("Parsed Prefixes: %s", nickPrefixes)); + logger.debug(String.format("Parsed Prefixes: %s", nickPrefixes)); } } else if (parameter.startsWith("CHANTYPES=")) { for (int typeIndex = 10; typeIndex < parameter.length(); ++typeIndex) { channelTypes.add(parameter.charAt(typeIndex)); } - logger.fine(String.format("Parsed Channel Types: %s", channelTypes)); + logger.debug(String.format("Parsed Channel Types: %s", channelTypes)); } } @@ -495,27 +501,24 @@ public class Connection extends AbstractExecutionThreadService implements Servic eventBus.post(new MotdReceived(this, motd.toString())); motd.setLength(0); + } else if (command.equalsIgnoreCase("KICK")) { + eventBus.post(new KickedFromChannel(this, parameters.get(0), reply.source().get(), parameters.get(1), getOptional(parameters, 2))); + /* okay, everything else. */ } else { eventBus.post(new UnknownReplyReceived(this, reply)); } - - if ((connectionStatus == 0x0f) && (connectionStatus != oldConnectionStatus)) { - /* connection succeeded! */ - established = true; - eventBus.post(new ConnectionEstablished(this)); - } - oldConnectionStatus = connectionStatus; } eventBus.post(new ConnectionClosed(this)); } catch (IOException ioe1) { - logger.log(Level.WARNING, "I/O error", ioe1); + logger.warn("I/O error", ioe1); eventBus.post(new ConnectionClosed(this, ioe1)); } catch (RuntimeException re1) { - logger.log(Level.SEVERE, "Runtime error", re1); + logger.error("Runtime error", re1); eventBus.post(new ConnectionClosed(this, re1)); } finally { - established = false; + established.set(false); + eventBus.unregister(this); logger.info("Closing Connection."); try { Closeables.close(connectionHandler, true); @@ -526,6 +529,13 @@ public class Connection extends AbstractExecutionThreadService implements Servic } + @Subscribe + public void connectionEstablished(ConnectionEstablished connectionEstablished) { + if (connectionEstablished.connection() == this) { + established.set(true); + } + } + // // PRIVATE METHODS // @@ -549,7 +559,7 @@ public class Connection extends AbstractExecutionThreadService implements Servic if (inetAddress.isPresent() && port.isPresent()) { eventBus.post(new DccSendReceived(this, client, messageWords[2], inetAddress.get(), port.get(), fileSize)); } else { - logger.warning(String.format("Received malformed DCC SEND: “%s”", message)); + logger.warn(String.format("Received malformed DCC SEND: “%s”", message)); } } else if (messageWords[1].equalsIgnoreCase("ACCEPT")) { Optional port = Optional.fromNullable(Ints.tryParse(messageWords[3])); @@ -557,7 +567,7 @@ public class Connection extends AbstractExecutionThreadService implements Servic if (port.isPresent()) { eventBus.post(new DccAcceptReceived(this, client, messageWords[2], port.get(), position)); } else { - logger.warning(String.format("Received malformed DCC ACCEPT: “%s”", message)); + logger.warn(String.format("Received malformed DCC ACCEPT: “%s”", message)); } } } @@ -711,7 +721,7 @@ public class Connection extends AbstractExecutionThreadService implements Servic commandBuilder.append(parameter); } - logger.finest(String.format(">> %s", commandBuilder)); + logger.trace(String.format(">> %s", commandBuilder)); outputStream.write((commandBuilder.toString() + "\r\n").getBytes("UTF-8")); outputStream.flush(); } @@ -742,6 +752,7 @@ public class Connection extends AbstractExecutionThreadService implements Servic public void close() throws IOException { Closeables.close(outputStream, true); Closeables.close(inputStreamReader, true); + Closeables.close(inputStream, true); } }