Browse Source

Merge pull request #112 from ShaneMcC/SeparatePendingKeys

Make ProcessJoin handle the pendingJoins queue.
pull/117/head
Chris Smith 8 years ago
parent
commit
0bada408ab

+ 1
- 1
common/src/com/dmdirc/parser/events/DataOutEvent.java View File

29
 import static com.google.common.base.Preconditions.checkNotNull;
29
 import static com.google.common.base.Preconditions.checkNotNull;
30
 
30
 
31
 /**
31
 /**
32
- * Called on every incoming line BEFORE being sent.
32
+ * Called on every outgoing line BEFORE being sent.
33
  */
33
  */
34
 public class DataOutEvent extends ParserEvent {
34
 public class DataOutEvent extends ParserEvent {
35
 
35
 

+ 2
- 44
irc/src/com/dmdirc/parser/irc/IRCParser.java View File

47
 import com.dmdirc.parser.interfaces.EncodingParser;
47
 import com.dmdirc.parser.interfaces.EncodingParser;
48
 import com.dmdirc.parser.interfaces.SecureParser;
48
 import com.dmdirc.parser.interfaces.SecureParser;
49
 import com.dmdirc.parser.irc.IRCReader.ReadLine;
49
 import com.dmdirc.parser.irc.IRCReader.ReadLine;
50
+import com.dmdirc.parser.irc.events.IRCDataOutEvent;
50
 import com.dmdirc.parser.irc.outputqueue.OutputQueue;
51
 import com.dmdirc.parser.irc.outputqueue.OutputQueue;
51
 
52
 
52
 import java.io.IOException;
53
 import java.io.IOException;
234
     private final WhoisResponseHandler whoisHandler;
235
     private final WhoisResponseHandler whoisHandler;
235
     /** Used to synchronize calls to resetState. */
236
     /** Used to synchronize calls to resetState. */
236
     private final Object resetStateSync = new Object();
237
     private final Object resetStateSync = new Object();
237
-    /** Pending Joins. */
238
-    private final Queue<String> pendingJoins = new LinkedList<>();
239
-    /** Pending Join Keys. */
240
-    private final Queue<String> pendingJoinKeys = new LinkedList<>();
241
 
238
 
242
     /**
239
     /**
243
      * Default constructor, ServerInfo and MyInfo need to be added separately (using IRC.me and IRC.server).
240
      * Default constructor, ServerInfo and MyInfo need to be added separately (using IRC.me and IRC.server).
551
      * @param fromParser True if parser sent the data, false if sent using .sendLine
548
      * @param fromParser True if parser sent the data, false if sent using .sendLine
552
      */
549
      */
553
     protected void callDataOut(final String data, final boolean fromParser) {
550
     protected void callDataOut(final String data, final boolean fromParser) {
554
-        getCallbackManager().publish(new DataOutEvent(this, LocalDateTime.now(), data));
551
+        getCallbackManager().publish(new IRCDataOutEvent(this, LocalDateTime.now(), data));
555
     }
552
     }
556
 
553
 
557
     /**
554
     /**
1059
                     }
1056
                     }
1060
                 }
1057
                 }
1061
             }
1058
             }
1062
-        } else if ("join".equalsIgnoreCase(newLine[0]) && newLine.length > 1) {
1063
-            final Queue<String> keys = new LinkedList<>();
1064
-
1065
-            if (newLine.length > 2) {
1066
-                keys.addAll(Arrays.asList(newLine[2].split(",")));
1067
-            }
1068
-
1069
-            // PendingJoins and PendingJoinKeys should always be the same length (even if no key was given).
1070
-            //
1071
-            // We don't get any errors for channels we try to join that we are already in
1072
-            // But the IRCD will still swallow the key attempt.
1073
-            //
1074
-            // Make sure that we always have a guessed key for every channel (even if null) and that we
1075
-            // don't have guesses for channels we are already in.
1076
-            for (final String chan : newLine[1].split(",")) {
1077
-                final String key = keys.poll();
1078
-                if (getChannel(chan) == null) {
1079
-                    pendingJoins.add(chan);
1080
-                    pendingJoinKeys.add(key);
1081
-                }
1082
-            }
1083
         }
1059
         }
1084
 
1060
 
1085
         return true;
1061
         return true;
1086
     }
1062
     }
1087
 
1063
 
1088
-    /**
1089
-     * Get the current pending Joins.
1090
-     *
1091
-     * @return Current pending Joins
1092
-     */
1093
-    public Queue<String> getPendingJoins() {
1094
-        return pendingJoins;
1095
-    }
1096
-
1097
-    /**
1098
-     * Get the current pending join keys.
1099
-     *
1100
-     * @return Current pending join keys.
1101
-     */
1102
-    public Queue<String> getPendingJoinKeys() {
1103
-        return pendingJoinKeys;
1104
-    }
1105
-
1106
     @Override
1064
     @Override
1107
     public String getNetworkName() {
1065
     public String getNetworkName() {
1108
         return networkName;
1066
         return networkName;

+ 56
- 0
irc/src/com/dmdirc/parser/irc/events/IRCDataOutEvent.java View File

1
+/*
2
+ * Copyright (c) 2006-2014 DMDirc Developers
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+
23
+package com.dmdirc.parser.irc.events;
24
+
25
+import com.dmdirc.parser.events.DataOutEvent;
26
+import com.dmdirc.parser.interfaces.Parser;
27
+import com.dmdirc.parser.irc.IRCParser;
28
+
29
+import java.time.LocalDateTime;
30
+
31
+import static com.google.common.base.Preconditions.checkNotNull;
32
+
33
+/**
34
+ * Called on every outgoing line BEFORE being sent.
35
+ *
36
+ * This extends the standard DataOutEvent to also pre-tokenise the data.
37
+ */
38
+public class IRCDataOutEvent extends DataOutEvent {
39
+
40
+    private final String[] tokenisedData;
41
+    private final String action;
42
+
43
+    public IRCDataOutEvent(final Parser parser, final LocalDateTime date, final String data) {
44
+        super(parser, date, data);
45
+        tokenisedData = IRCParser.tokeniseLine(checkNotNull(data));
46
+        action = tokenisedData[0].toUpperCase();
47
+    }
48
+
49
+    public String[] getTokenisedData() {
50
+        return tokenisedData;
51
+    }
52
+
53
+    public String getAction() {
54
+        return action;
55
+    }
56
+}

+ 56
- 8
irc/src/com/dmdirc/parser/irc/processors/ProcessJoin.java View File

26
 import com.dmdirc.parser.common.QueuePriority;
26
 import com.dmdirc.parser.common.QueuePriority;
27
 import com.dmdirc.parser.events.ChannelJoinEvent;
27
 import com.dmdirc.parser.events.ChannelJoinEvent;
28
 import com.dmdirc.parser.events.ChannelSelfJoinEvent;
28
 import com.dmdirc.parser.events.ChannelSelfJoinEvent;
29
+import com.dmdirc.parser.events.DataOutEvent;
29
 import com.dmdirc.parser.interfaces.ChannelClientInfo;
30
 import com.dmdirc.parser.interfaces.ChannelClientInfo;
30
 import com.dmdirc.parser.interfaces.ChannelInfo;
31
 import com.dmdirc.parser.interfaces.ChannelInfo;
31
 import com.dmdirc.parser.irc.CapabilityState;
32
 import com.dmdirc.parser.irc.CapabilityState;
36
 import com.dmdirc.parser.irc.ModeManager;
37
 import com.dmdirc.parser.irc.ModeManager;
37
 import com.dmdirc.parser.irc.PrefixModeManager;
38
 import com.dmdirc.parser.irc.PrefixModeManager;
38
 import com.dmdirc.parser.irc.ProcessorNotFoundException;
39
 import com.dmdirc.parser.irc.ProcessorNotFoundException;
40
+import com.dmdirc.parser.irc.events.IRCDataOutEvent;
41
+import net.engio.mbassy.listener.Handler;
42
+import net.engio.mbassy.listener.Invoke;
39
 
43
 
40
 import java.time.LocalDateTime;
44
 import java.time.LocalDateTime;
41
 import java.util.Arrays;
45
 import java.util.Arrays;
46
+import java.util.LinkedList;
47
+import java.util.Queue;
42
 
48
 
43
 import javax.inject.Inject;
49
 import javax.inject.Inject;
44
 import javax.inject.Named;
50
 import javax.inject.Named;
54
     private final ModeManager userModeManager;
60
     private final ModeManager userModeManager;
55
     /** Mode manager to use for channel modes. */
61
     /** Mode manager to use for channel modes. */
56
     private final ModeManager chanModeManager;
62
     private final ModeManager chanModeManager;
63
+    /** Pending Joins. */
64
+    private final Queue<String> pendingJoins = new LinkedList<>();
65
+    /** Pending Join Keys. */
66
+    private final Queue<String> pendingJoinKeys = new LinkedList<>();
57
 
67
 
58
     /**
68
     /**
59
      * Create a new instance of the IRCProcessor Object.
69
      * Create a new instance of the IRCProcessor Object.
71
         this.prefixModeManager = prefixModeManager;
81
         this.prefixModeManager = prefixModeManager;
72
         this.userModeManager = userModeManager;
82
         this.userModeManager = userModeManager;
73
         this.chanModeManager = chanModeManager;
83
         this.chanModeManager = chanModeManager;
84
+
85
+        getCallbackManager().subscribe(this);
74
     }
86
     }
75
 
87
 
76
     /**
88
     /**
171
             parser.addChannel(iChannel);
183
             parser.addChannel(iChannel);
172
             sendString("MODE " + iChannel.getName(), QueuePriority.LOW);
184
             sendString("MODE " + iChannel.getName(), QueuePriority.LOW);
173
 
185
 
174
-            final String pendingJoin = parser.getPendingJoins().poll();
175
-            final String pendingJoinKey = parser.getPendingJoinKeys().poll();
176
-            if (pendingJoin.equalsIgnoreCase(channelName)) {
186
+            final String pendingJoin = pendingJoins.poll();
187
+            final String pendingJoinKey = pendingJoinKeys.poll();
188
+            if (pendingJoin != null && pendingJoin.equalsIgnoreCase(channelName)) {
177
                 callDebugInfo(IRCParser.DEBUG_INFO, "processJoin: Guessing channel Key: " + pendingJoin + " -> " + pendingJoinKey);
189
                 callDebugInfo(IRCParser.DEBUG_INFO, "processJoin: Guessing channel Key: " + pendingJoin + " -> " + pendingJoinKey);
178
                 iChannel.setInternalPassword(pendingJoinKey == null ? "" : pendingJoinKey);
190
                 iChannel.setInternalPassword(pendingJoinKey == null ? "" : pendingJoinKey);
179
             } else {
191
             } else {
180
-                // Out of sync, clear.
181
-                parser.getPendingJoins().clear();
182
-                parser.getPendingJoinKeys().clear();
192
+                // Out of sync, clear
193
+                callDebugInfo(IRCParser.DEBUG_INFO, "processJoin: pending join keys out of sync (Got: " + pendingJoin + ", Wanted: " + channelName + ") - Clearing.");
194
+                pendingJoins.clear();
195
+                pendingJoinKeys.clear();
183
             }
196
             }
184
 
197
 
185
             callChannelSelfJoin(iChannel);
198
             callChannelSelfJoin(iChannel);
186
         } else {
199
         } else {
187
             // Some kind of failed to join, pop the pending join queues.
200
             // Some kind of failed to join, pop the pending join queues.
188
-            parser.getPendingJoins().poll();
189
-            parser.getPendingJoinKeys().poll();
201
+            final String pendingJoin = pendingJoins.poll();
202
+            final String pendingJoinKey = pendingJoinKeys.poll();
203
+            callDebugInfo(IRCParser.DEBUG_INFO, "processJoin: Failed to join channel (" + sParam + ") - Skipping " + pendingJoin + " (" + pendingJoinKey + ")");
204
+        }
205
+    }
206
+
207
+    @Handler(condition = "msg.action == 'JOIN'")
208
+    public void handleDataOut(final IRCDataOutEvent event) {
209
+        // As long as this is called before the resulting DataIn
210
+        // Processors fire then this will work, otherwise we'll end
211
+        // up with an out-of-sync pendingJoins list.
212
+
213
+        final String[] newLine = event.getTokenisedData();
214
+        if (newLine.length > 1) {
215
+            final Queue<String> keys = new LinkedList<>();
216
+
217
+            if (newLine.length > 2) {
218
+                keys.addAll(Arrays.asList(newLine[2].split(",")));
219
+            }
220
+
221
+            // PendingJoins and PendingJoinKeys should always be the same length (even if no key was given).
222
+            //
223
+            // We don't get any errors for channels we try to join that we are already in
224
+            // But the IRCD will still swallow the key attempt.
225
+            //
226
+            // Make sure that we always have a guessed key for every channel (even if null) and that we
227
+            // don't have guesses for channels we are already in.
228
+            for (final String chan : newLine[1].split(",")) {
229
+                final String key = keys.poll();
230
+                if (getChannel(chan) == null) {
231
+                    callDebugInfo(IRCParser.DEBUG_INFO, "processJoin: Intercepted possible channel Key: " + chan + " -> " + key);
232
+                    pendingJoins.add(chan);
233
+                    pendingJoinKeys.add(key);
234
+                } else {
235
+                    callDebugInfo(IRCParser.DEBUG_INFO, "processJoin: Ignoring possible channel Key for existing channel: " + chan + " -> " + key);
236
+                }
237
+            }
190
         }
238
         }
191
     }
239
     }
192
 
240
 

Loading…
Cancel
Save