|
@@ -36,8 +36,7 @@ import java.util.concurrent.Semaphore;
|
36
|
36
|
* @version $Id: DCC.java 969 2007-04-30 18:38:20Z ShaneMcC $
|
37
|
37
|
*/
|
38
|
38
|
public abstract class DCC implements Runnable {
|
39
|
|
-
|
40
|
|
- /** Address. */
|
|
39
|
+ /** Address. */
|
41
|
40
|
protected long address = 0;
|
42
|
41
|
/** Port. */
|
43
|
42
|
protected int port = 0;
|
|
@@ -45,38 +44,38 @@ public abstract class DCC implements Runnable {
|
45
|
44
|
protected Socket socket;
|
46
|
45
|
/** The Thread in use for this. */
|
47
|
46
|
private volatile Thread myThread;
|
48
|
|
- /** Are we already running? */
|
|
47
|
+ /** Are we already running? */
|
49
|
48
|
protected boolean running = false;
|
50
|
49
|
/** Are we a listen socket? */
|
51
|
50
|
protected boolean listen = false;
|
52
|
51
|
|
53
|
|
- /**
|
54
|
|
- * The current socket in use is this is a listen socket. This reference
|
55
|
|
- * may be changed if and only if exactly one permit from the
|
56
|
|
- * <code>serverSocketSem</code> and <code>serverListenignSem</code>
|
57
|
|
- * semaphores is held by the thread doing the modification.
|
58
|
|
- */
|
|
52
|
+ /**
|
|
53
|
+ * The current socket in use if this is a listen socket.
|
|
54
|
+ * This reference may be changed if and only if exactly one permit from the
|
|
55
|
+ * <code>serverSocketSem</code> and <code>serverListenignSem</code>
|
|
56
|
+ * semaphores is held by the thread doing the modification.
|
|
57
|
+ */
|
59
|
58
|
private ServerSocket serverSocket;
|
60
|
59
|
|
61
|
|
- /**
|
62
|
|
- * Semaphore to control write access to ServerSocket. If an object acquires
|
63
|
|
- * a permit from the <code>serverSocketSem</code>, then
|
64
|
|
- * <code>serverSocket</code> is <em>guaranteed</em> not to be externally
|
65
|
|
- * modified until that permit is released, <em>unless</em> the object also
|
66
|
|
- * acquires a permit from the <code>serverListeningSem</code>.
|
67
|
|
- */
|
68
|
|
- private final Semaphore serverSocketSem = new Semaphore(1);
|
69
|
|
-
|
70
|
|
- /**
|
71
|
|
- * Semaphore used when we're blocking waiting for connections. If an object
|
72
|
|
- * acquires a permit from the <code>serverListeningSem</code>, then it is
|
73
|
|
- * <em>guaranteed</em> that the {@link #run()} method is blocking waiting
|
74
|
|
- * for incoming connections. In addition, it is <em>guaranteed</em> that
|
75
|
|
- * the {@link #run()} method is holding the <code>serverSocketSem</code>
|
76
|
|
- * permit, and it will continue holding that permit until it can reaquire
|
77
|
|
- * the <code>serverListeningSem</code> permit.
|
78
|
|
- */
|
79
|
|
- private final Semaphore serverListeningSem = new Semaphore(0);
|
|
60
|
+ /**
|
|
61
|
+ * Semaphore to control write access to ServerSocket.
|
|
62
|
+ * If an object acquires a permit from the <code>serverSocketSem</code>, then
|
|
63
|
+ * <code>serverSocket</code> is <em>guaranteed</em> not to be externally
|
|
64
|
+ * modified until that permit is released, <em>unless</em> the object also
|
|
65
|
+ * acquires a permit from the <code>serverListeningSem</code>.
|
|
66
|
+ */
|
|
67
|
+ private final Semaphore serverSocketSem = new Semaphore(1);
|
|
68
|
+
|
|
69
|
+ /**
|
|
70
|
+ * Semaphore used when we're blocking waiting for connections.
|
|
71
|
+ * If an object acquires a permit from the <code>serverListeningSem</code>,
|
|
72
|
+ * then it is <em>guaranteed</em> that the {@link #run()} method is blocking
|
|
73
|
+ * waiting for incoming connections. In addition, it is <em>guaranteed</em>
|
|
74
|
+ * that the {@link #run()} method is holding the <code>serverSocketSem</code>
|
|
75
|
+ * permit, and it will continue holding that permit until it can reaquire
|
|
76
|
+ * the <code>serverListeningSem</code> permit.
|
|
77
|
+ */
|
|
78
|
+ private final Semaphore serverListeningSem = new Semaphore(0);
|
80
|
79
|
|
81
|
80
|
/**
|
82
|
81
|
* Creates a new instance of DCC.
|
|
@@ -110,17 +109,17 @@ public abstract class DCC implements Runnable {
|
110
|
109
|
|
111
|
110
|
/**
|
112
|
111
|
* Start a listen socket rather than a connect socket.
|
113
|
|
- *
|
114
|
|
- * @throws IOException If the listen socket can't be created
|
115
|
|
- */
|
|
112
|
+ *
|
|
113
|
+ * @throws IOException If the listen socket can't be created
|
|
114
|
+ */
|
116
|
115
|
public void listen() throws IOException {
|
117
|
116
|
listen = true;
|
118
|
117
|
|
119
|
|
- serverSocketSem.acquireUninterruptibly();
|
|
118
|
+ serverSocketSem.acquireUninterruptibly();
|
120
|
119
|
serverSocket = new ServerSocket(0, 1);
|
121
|
|
- serverSocketSem.release();
|
|
120
|
+ serverSocketSem.release();
|
122
|
121
|
|
123
|
|
- connect();
|
|
122
|
+ connect();
|
124
|
123
|
}
|
125
|
124
|
|
126
|
125
|
/**
|
|
@@ -136,9 +135,9 @@ public abstract class DCC implements Runnable {
|
136
|
135
|
|
137
|
136
|
for (int i = startPort; i <= endPort; ++i) {
|
138
|
137
|
try {
|
139
|
|
- serverSocketSem.acquireUninterruptibly();
|
|
138
|
+ serverSocketSem.acquireUninterruptibly();
|
140
|
139
|
serverSocket = new ServerSocket(i, 1);
|
141
|
|
- serverSocketSem.release();
|
|
140
|
+ serverSocketSem.release();
|
142
|
141
|
// Found a socket we can use!
|
143
|
142
|
break;
|
144
|
143
|
} catch (IOException ioe) {
|
|
@@ -167,30 +166,28 @@ public abstract class DCC implements Runnable {
|
167
|
166
|
Thread thisThread = Thread.currentThread();
|
168
|
167
|
|
169
|
168
|
while (myThread == thisThread) {
|
170
|
|
- serverSocketSem.acquireUninterruptibly();
|
|
169
|
+ serverSocketSem.acquireUninterruptibly();
|
171
|
170
|
|
172
|
171
|
if (serverSocket == null) {
|
173
|
|
- serverSocketSem.release();
|
174
|
|
-
|
|
172
|
+ serverSocketSem.release();
|
|
173
|
+
|
175
|
174
|
if (!handleSocket()) {
|
176
|
175
|
close();
|
177
|
176
|
break;
|
178
|
177
|
}
|
179
|
178
|
} else {
|
180
|
179
|
try {
|
181
|
|
- serverListeningSem.release();
|
|
180
|
+ serverListeningSem.release();
|
182
|
181
|
socket = serverSocket.accept();
|
183
|
182
|
serverSocket.close();
|
184
|
183
|
socketOpened();
|
185
|
184
|
} catch (IOException ioe) {
|
186
|
185
|
break;
|
187
|
186
|
} finally {
|
188
|
|
- serverListeningSem.acquireUninterruptibly();
|
189
|
|
-
|
190
|
|
- serverSocket = null;
|
191
|
|
-
|
192
|
|
- serverSocketSem.release();
|
193
|
|
- }
|
|
187
|
+ serverListeningSem.acquireUninterruptibly();
|
|
188
|
+ serverSocket = null;
|
|
189
|
+ serverSocketSem.release();
|
|
190
|
+ }
|
194
|
191
|
}
|
195
|
192
|
}
|
196
|
193
|
// Socket closed
|
|
@@ -203,16 +200,15 @@ public abstract class DCC implements Runnable {
|
203
|
200
|
* Called to close the socket
|
204
|
201
|
*/
|
205
|
202
|
protected void close() {
|
206
|
|
- boolean haveSLS = false;
|
|
203
|
+ boolean haveSLS = false;
|
207
|
204
|
|
208
|
|
- while (!serverSocketSem.tryAcquire() &&
|
209
|
|
- !(haveSLS = serverListeningSem.tryAcquire())) {
|
210
|
|
- try {
|
211
|
|
- Thread.sleep(100);
|
212
|
|
- } catch (InterruptedException ex) {
|
213
|
|
- // Do we care? I doubt we do! Should be unchecked damnit.
|
214
|
|
- }
|
215
|
|
- }
|
|
205
|
+ while (!serverSocketSem.tryAcquire() && !(haveSLS = serverListeningSem.tryAcquire())) {
|
|
206
|
+ try {
|
|
207
|
+ Thread.sleep(100);
|
|
208
|
+ } catch (InterruptedException ex) {
|
|
209
|
+ // Do we care? I doubt we do! Should be unchecked damnit.
|
|
210
|
+ }
|
|
211
|
+ }
|
216
|
212
|
|
217
|
213
|
if (serverSocket != null) {
|
218
|
214
|
try {
|
|
@@ -223,11 +219,11 @@ public abstract class DCC implements Runnable {
|
223
|
219
|
serverSocket = null;
|
224
|
220
|
}
|
225
|
221
|
|
226
|
|
- if (haveSLS) {
|
227
|
|
- serverListeningSem.release();
|
228
|
|
- } else {
|
229
|
|
- serverSocketSem.release();
|
230
|
|
- }
|
|
222
|
+ if (haveSLS) {
|
|
223
|
+ serverListeningSem.release();
|
|
224
|
+ } else {
|
|
225
|
+ serverSocketSem.release();
|
|
226
|
+ }
|
231
|
227
|
|
232
|
228
|
if (socket != null) {
|
233
|
229
|
try {
|