2008-08-08 02:37:18 +02:00
|
|
|
/*
|
2011-12-09 06:18:34 +01:00
|
|
|
* Copyright 2011 The Netty Project
|
2008-08-08 02:37:18 +02:00
|
|
|
*
|
2011-12-09 06:18:34 +01:00
|
|
|
* The Netty Project licenses this file to you under the Apache License,
|
|
|
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
|
|
* with the License. You may obtain a copy of the License at:
|
2008-08-08 02:37:18 +02:00
|
|
|
*
|
2011-12-09 06:18:34 +01:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2008-08-08 03:27:24 +02:00
|
|
|
*
|
2009-08-28 09:15:49 +02:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
2011-12-09 06:18:34 +01:00
|
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
2009-08-28 09:15:49 +02:00
|
|
|
* License for the specific language governing permissions and limitations
|
|
|
|
* under the License.
|
2008-08-08 02:37:18 +02:00
|
|
|
*/
|
2011-12-09 04:38:59 +01:00
|
|
|
package io.netty.channel;
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
import io.netty.logging.InternalLogger;
|
|
|
|
import io.netty.logging.InternalLoggerFactory;
|
|
|
|
import io.netty.util.DefaultAttributeMap;
|
|
|
|
import io.netty.util.internal.ConcurrentHashMap;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
2008-08-08 02:37:18 +02:00
|
|
|
import java.net.SocketAddress;
|
2012-05-01 10:19:41 +02:00
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
2009-02-16 12:59:33 +01:00
|
|
|
import java.util.concurrent.ConcurrentMap;
|
2008-08-08 02:37:18 +02:00
|
|
|
|
|
|
|
/**
|
2008-09-02 09:13:20 +02:00
|
|
|
* A skeletal {@link Channel} implementation.
|
2008-08-08 02:37:18 +02:00
|
|
|
*/
|
2012-05-01 10:19:41 +02:00
|
|
|
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
|
|
|
|
|
|
|
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannel.class);
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2009-02-16 12:59:33 +01:00
|
|
|
static final ConcurrentMap<Integer, Channel> allChannels = new ConcurrentHashMap<Integer, Channel>();
|
|
|
|
|
|
|
|
private static Integer allocateId(Channel channel) {
|
|
|
|
Integer id = Integer.valueOf(System.identityHashCode(channel));
|
|
|
|
for (;;) {
|
|
|
|
// Loop until a unique ID is acquired.
|
|
|
|
// It should be found in one loop practically.
|
|
|
|
if (allChannels.putIfAbsent(id, channel) == null) {
|
|
|
|
// Successfully acquired.
|
|
|
|
return id;
|
|
|
|
} else {
|
|
|
|
// Taken by other channel at almost the same moment.
|
|
|
|
id = Integer.valueOf(id.intValue() + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-19 08:29:43 +02:00
|
|
|
private final Integer id;
|
2008-08-08 02:37:18 +02:00
|
|
|
private final Channel parent;
|
2012-05-01 10:19:41 +02:00
|
|
|
private final Unsafe unsafe;
|
2012-05-01 10:48:06 +02:00
|
|
|
private final ChannelPipeline pipeline = new DefaultChannelPipeline(this);
|
2012-05-01 10:19:41 +02:00
|
|
|
private final List<ChannelFutureListener> closureListeners = new ArrayList<ChannelFutureListener>(4);
|
2012-05-01 10:48:06 +02:00
|
|
|
private final ChannelFuture succeededFuture = new SucceededChannelFuture(this);
|
2012-05-01 10:19:41 +02:00
|
|
|
|
|
|
|
private volatile EventLoop eventLoop;
|
2012-05-02 14:05:53 +02:00
|
|
|
private volatile boolean registered;
|
2012-05-01 10:19:41 +02:00
|
|
|
private volatile boolean notifiedClosureListeners;
|
2012-05-02 14:05:53 +02:00
|
|
|
private ChannelFuture connectFuture;
|
2008-08-08 02:37:18 +02:00
|
|
|
|
|
|
|
/** Cache for the string representation of this channel */
|
2012-05-01 10:19:41 +02:00
|
|
|
private boolean strValActive;
|
2008-08-08 02:37:18 +02:00
|
|
|
private String strVal;
|
2012-05-01 10:19:41 +02:00
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
|
|
|
* Creates a new instance.
|
|
|
|
*
|
|
|
|
* @param parent
|
|
|
|
* the parent of this channel. {@code null} if there's no parent.
|
|
|
|
*/
|
2012-05-01 10:19:41 +02:00
|
|
|
protected AbstractChannel(Channel parent) {
|
2010-05-19 08:29:43 +02:00
|
|
|
id = allocateId(this);
|
2012-05-01 10:19:41 +02:00
|
|
|
this.parent = parent;
|
|
|
|
unsafe = new DefaultUnsafe();
|
2010-05-19 08:29:43 +02:00
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
closureListeners.add(new ChannelFutureListener() {
|
|
|
|
@Override
|
|
|
|
public void operationComplete(ChannelFuture future) {
|
|
|
|
allChannels.remove(id());
|
|
|
|
}
|
|
|
|
});
|
2010-05-19 08:29:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* (Internal use only) Creates a new temporary instance with the specified
|
|
|
|
* ID.
|
|
|
|
*
|
|
|
|
* @param parent
|
|
|
|
* the parent of this channel. {@code null} if there's no parent.
|
|
|
|
*/
|
2012-05-01 10:19:41 +02:00
|
|
|
protected AbstractChannel(Integer id, Channel parent) {
|
2010-05-19 08:29:43 +02:00
|
|
|
this.id = id;
|
|
|
|
this.parent = parent;
|
2012-05-01 10:19:41 +02:00
|
|
|
unsafe = new DefaultUnsafe();
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public final Integer id() {
|
2008-08-08 02:37:18 +02:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public Channel parent() {
|
2008-08-08 02:37:18 +02:00
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public ChannelPipeline pipeline() {
|
2008-08-08 02:37:18 +02:00
|
|
|
return pipeline;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public EventLoop eventLoop() {
|
|
|
|
return eventLoop;
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2012-05-02 14:05:53 +02:00
|
|
|
@Override
|
|
|
|
public boolean isRegistered() {
|
|
|
|
return registered;
|
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void bind(SocketAddress localAddress, ChannelFuture future) {
|
|
|
|
pipeline().bind(localAddress, future);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void connect(SocketAddress remoteAddress, ChannelFuture future) {
|
|
|
|
pipeline().connect(remoteAddress, future);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelFuture future) {
|
|
|
|
pipeline().connect(remoteAddress, localAddress, future);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void disconnect(ChannelFuture future) {
|
|
|
|
pipeline().disconnect(future);
|
2008-10-02 06:40:46 +02:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void close(ChannelFuture future) {
|
|
|
|
pipeline().close(future);
|
2008-11-26 10:21:00 +01:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void deregister(ChannelFuture future) {
|
|
|
|
pipeline().deregister(future);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public ChannelBufferHolder<Object> out() {
|
|
|
|
return pipeline().nextOut();
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void flush(ChannelFuture future) {
|
|
|
|
pipeline().flush(future);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void write(Object message, ChannelFuture future) {
|
|
|
|
pipeline.write(message, future);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2012-05-01 10:48:06 +02:00
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ChannelFuture newFuture() {
|
|
|
|
return new DefaultChannelFuture(this, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ChannelFuture newSucceededFuture() {
|
|
|
|
return succeededFuture;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public ChannelFuture newFailedFuture(Throwable cause) {
|
|
|
|
return new FailedChannelFuture(this, cause);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public void addClosureListener(final ChannelFutureListener listener) {
|
|
|
|
if (listener == null) {
|
|
|
|
throw new NullPointerException("listener");
|
|
|
|
}
|
|
|
|
synchronized (closureListeners) {
|
|
|
|
if (notifiedClosureListeners) {
|
|
|
|
eventLoop().execute(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
notifyClosureListener(listener);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
closureListeners.add(listener);
|
|
|
|
}
|
|
|
|
}
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2012-05-01 10:48:06 +02:00
|
|
|
@Override
|
|
|
|
public void removeClosureListener(ChannelFutureListener listener) {
|
|
|
|
if (listener == null) {
|
|
|
|
throw new NullPointerException("listener");
|
|
|
|
}
|
|
|
|
synchronized (closureListeners) {
|
|
|
|
if (!notifiedClosureListeners) {
|
|
|
|
closureListeners.remove(listener);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-02 14:05:53 +02:00
|
|
|
private void notifyClosureListeners() {
|
2012-05-01 10:19:41 +02:00
|
|
|
final ChannelFutureListener[] array;
|
|
|
|
synchronized (closureListeners) {
|
|
|
|
if (notifiedClosureListeners) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
notifiedClosureListeners = true;
|
|
|
|
array = closureListeners.toArray(new ChannelFutureListener[closureListeners.size()]);
|
|
|
|
closureListeners.clear();
|
|
|
|
}
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
eventLoop().execute(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
for (ChannelFutureListener l: array) {
|
|
|
|
notifyClosureListener(l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
private void notifyClosureListener(final ChannelFutureListener listener) {
|
|
|
|
try {
|
2012-05-01 10:48:06 +02:00
|
|
|
listener.operationComplete(newSucceededFuture());
|
2012-05-01 10:19:41 +02:00
|
|
|
} catch (Exception e) {
|
|
|
|
logger.warn("Failed to notify a closure listener.", e);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public Unsafe unsafe() {
|
|
|
|
return unsafe;
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
/**
|
|
|
|
* Returns the {@linkplain System#identityHashCode(Object) identity hash code}
|
|
|
|
* of this channel.
|
|
|
|
*/
|
2010-11-12 01:45:39 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public final int hashCode() {
|
|
|
|
return System.identityHashCode(this);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
/**
|
|
|
|
* Returns {@code true} if and only if the specified object is identical
|
|
|
|
* with this channel (i.e: {@code this == o}).
|
|
|
|
*/
|
2011-12-07 07:54:15 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public final boolean equals(Object o) {
|
|
|
|
return this == o;
|
2011-12-07 07:54:15 +01:00
|
|
|
}
|
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
/**
|
|
|
|
* Compares the {@linkplain #id() ID} of the two channels.
|
|
|
|
*/
|
2011-12-07 07:54:15 +01:00
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public final int compareTo(Channel o) {
|
|
|
|
return id().compareTo(o.id());
|
2011-12-07 07:54:15 +01:00
|
|
|
}
|
2012-05-01 10:19:41 +02:00
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
|
|
|
* Returns the {@link String} representation of this channel. The returned
|
2012-05-01 10:19:41 +02:00
|
|
|
* string contains the {@linkplain #id() ID}, {@linkplain #localAddress() local address},
|
|
|
|
* and {@linkplain #remoteAddress() remote address} of this channel for
|
2008-09-02 09:13:20 +02:00
|
|
|
* easier identification.
|
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
2012-05-01 10:19:41 +02:00
|
|
|
boolean active = isActive();
|
|
|
|
if (strValActive == active && strVal != null) {
|
2008-08-08 02:37:18 +02:00
|
|
|
return strVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder buf = new StringBuilder(128);
|
2009-02-16 12:59:33 +01:00
|
|
|
buf.append("[id: 0x");
|
2009-02-16 15:32:40 +01:00
|
|
|
buf.append(getIdString());
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
SocketAddress localAddress = localAddress();
|
|
|
|
SocketAddress remoteAddress = remoteAddress();
|
2009-06-23 09:20:57 +02:00
|
|
|
if (remoteAddress != null) {
|
2008-08-08 02:37:18 +02:00
|
|
|
buf.append(", ");
|
2012-05-01 10:19:41 +02:00
|
|
|
if (parent() == null) {
|
2009-06-23 09:20:57 +02:00
|
|
|
buf.append(localAddress);
|
2012-05-01 10:19:41 +02:00
|
|
|
buf.append(active? " => " : " :> ");
|
2009-06-23 09:20:57 +02:00
|
|
|
buf.append(remoteAddress);
|
2008-08-08 02:37:18 +02:00
|
|
|
} else {
|
2009-06-23 09:20:57 +02:00
|
|
|
buf.append(remoteAddress);
|
2012-05-01 10:19:41 +02:00
|
|
|
buf.append(active? " => " : " :> ");
|
2009-06-23 09:20:57 +02:00
|
|
|
buf.append(localAddress);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
2009-06-23 09:20:57 +02:00
|
|
|
} else if (localAddress != null) {
|
2008-08-08 02:37:18 +02:00
|
|
|
buf.append(", ");
|
2009-06-23 09:20:57 +02:00
|
|
|
buf.append(localAddress);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2009-02-16 12:59:33 +01:00
|
|
|
buf.append(']');
|
2008-08-08 02:37:18 +02:00
|
|
|
|
2009-02-09 09:00:26 +01:00
|
|
|
String strVal = buf.toString();
|
2010-06-30 11:17:08 +02:00
|
|
|
this.strVal = strVal;
|
2012-05-01 10:19:41 +02:00
|
|
|
strValActive = active;
|
2009-02-09 09:00:26 +01:00
|
|
|
return strVal;
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
2009-02-16 15:32:40 +01:00
|
|
|
|
|
|
|
private String getIdString() {
|
|
|
|
String answer = Integer.toHexString(id.intValue());
|
|
|
|
switch (answer.length()) {
|
|
|
|
case 0:
|
|
|
|
answer = "00000000";
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
answer = "0000000" + answer;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
answer = "000000" + answer;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
answer = "00000" + answer;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
answer = "0000" + answer;
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
answer = "000" + answer;
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
answer = "00" + answer;
|
|
|
|
break;
|
|
|
|
case 7:
|
|
|
|
answer = "0" + answer;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return answer;
|
|
|
|
}
|
2010-01-09 06:40:40 +01:00
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
private class DefaultUnsafe implements Unsafe {
|
2010-01-09 06:40:40 +01:00
|
|
|
|
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public java.nio.channels.Channel ch() {
|
|
|
|
return javaChannel();
|
2010-01-09 06:40:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2012-05-01 10:19:41 +02:00
|
|
|
public ChannelBufferHolder<Object> out() {
|
|
|
|
return firstOut();
|
2010-01-09 06:40:40 +01:00
|
|
|
}
|
|
|
|
|
2012-05-02 08:01:58 +02:00
|
|
|
@Override
|
|
|
|
public SocketAddress localAddress() {
|
|
|
|
return localAddress0();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public SocketAddress remoteAddress() {
|
|
|
|
// TODO Auto-generated method stub
|
|
|
|
return remoteAddress0();
|
|
|
|
}
|
|
|
|
|
2012-05-01 16:18:29 +02:00
|
|
|
@Override
|
|
|
|
public void register(EventLoop eventLoop, ChannelFuture future) {
|
|
|
|
if (eventLoop == null) {
|
|
|
|
throw new NullPointerException("eventLoop");
|
|
|
|
}
|
|
|
|
if (AbstractChannel.this.eventLoop != null) {
|
|
|
|
throw new IllegalStateException("registered to an event loop already");
|
|
|
|
}
|
|
|
|
AbstractChannel.this.eventLoop = eventLoop;
|
|
|
|
|
|
|
|
assert eventLoop().inEventLoop();
|
|
|
|
doRegister(future);
|
2012-05-02 14:05:53 +02:00
|
|
|
assert future.isDone();
|
|
|
|
if (registered = future.isSuccess()) {
|
|
|
|
pipeline().fireChannelRegistered();
|
|
|
|
}
|
2012-05-01 16:18:29 +02:00
|
|
|
}
|
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
@Override
|
|
|
|
public void bind(final SocketAddress localAddress, final ChannelFuture future) {
|
|
|
|
if (eventLoop().inEventLoop()) {
|
|
|
|
doBind(localAddress, future);
|
|
|
|
} else {
|
|
|
|
eventLoop().execute(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
doBind(localAddress, future);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void connect(final SocketAddress remoteAddress, final SocketAddress localAddress, final ChannelFuture future) {
|
2012-05-02 14:05:53 +02:00
|
|
|
// XXX: What if a user makes a connection attempt twice?
|
2012-05-01 10:19:41 +02:00
|
|
|
if (eventLoop().inEventLoop()) {
|
|
|
|
doConnect(remoteAddress, localAddress, future);
|
2012-05-02 14:05:53 +02:00
|
|
|
if (!future.isDone()) {
|
|
|
|
connectFuture = future;
|
|
|
|
}
|
2012-05-01 10:19:41 +02:00
|
|
|
} else {
|
|
|
|
eventLoop().execute(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
doConnect(remoteAddress, localAddress, future);
|
2012-05-02 14:05:53 +02:00
|
|
|
if (!future.isDone()) {
|
|
|
|
connectFuture = future;
|
|
|
|
}
|
2012-05-01 10:19:41 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-02 14:05:53 +02:00
|
|
|
@Override
|
|
|
|
public void finishConnect() {
|
|
|
|
assert eventLoop().inEventLoop();
|
|
|
|
assert connectFuture != null;
|
|
|
|
doFinishConnect(connectFuture);
|
|
|
|
}
|
|
|
|
|
2012-05-01 10:19:41 +02:00
|
|
|
@Override
|
|
|
|
public void disconnect(final ChannelFuture future) {
|
|
|
|
if (eventLoop().inEventLoop()) {
|
|
|
|
doDisconnect(future);
|
|
|
|
} else {
|
|
|
|
eventLoop().execute(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
doDisconnect(future);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void close(final ChannelFuture future) {
|
|
|
|
if (eventLoop().inEventLoop()) {
|
|
|
|
doClose(future);
|
2012-05-02 14:05:53 +02:00
|
|
|
notifyClosureListeners();
|
2012-05-01 10:19:41 +02:00
|
|
|
} else {
|
|
|
|
eventLoop().execute(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
doClose(future);
|
2012-05-02 14:05:53 +02:00
|
|
|
notifyClosureListeners();
|
2012-05-01 10:19:41 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void deregister(final ChannelFuture future) {
|
|
|
|
if (eventLoop().inEventLoop()) {
|
2012-05-01 16:19:31 +02:00
|
|
|
try {
|
|
|
|
doDeregister(future);
|
|
|
|
} finally {
|
2012-05-02 14:05:53 +02:00
|
|
|
registered = false;
|
|
|
|
pipeline().fireChannelUnregistered();
|
2012-05-01 16:19:31 +02:00
|
|
|
eventLoop = null;
|
|
|
|
}
|
2012-05-01 10:19:41 +02:00
|
|
|
} else {
|
|
|
|
eventLoop().execute(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
2012-05-01 16:19:31 +02:00
|
|
|
try {
|
|
|
|
doDeregister(future);
|
|
|
|
} finally {
|
2012-05-02 14:05:53 +02:00
|
|
|
registered = false;
|
|
|
|
pipeline().fireChannelUnregistered();
|
2012-05-01 16:19:31 +02:00
|
|
|
eventLoop = null;
|
|
|
|
}
|
2012-05-01 10:19:41 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int read() throws IOException {
|
|
|
|
assert eventLoop().inEventLoop();
|
|
|
|
return doRead();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int flush(final ChannelFuture future) {
|
|
|
|
if (eventLoop().inEventLoop()) {
|
|
|
|
return doFlush(future);
|
|
|
|
} else {
|
|
|
|
eventLoop().execute(new Runnable() {
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
doFlush(future);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return -1; // Unknown
|
|
|
|
}
|
2010-01-09 06:40:40 +01:00
|
|
|
}
|
|
|
|
}
|
2012-05-01 10:19:41 +02:00
|
|
|
|
|
|
|
protected abstract java.nio.channels.Channel javaChannel();
|
|
|
|
protected abstract ChannelBufferHolder<Object> firstOut();
|
|
|
|
|
2012-05-02 08:01:58 +02:00
|
|
|
protected abstract SocketAddress localAddress0();
|
|
|
|
protected abstract SocketAddress remoteAddress0();
|
|
|
|
|
2012-05-01 16:18:29 +02:00
|
|
|
protected abstract void doRegister(ChannelFuture future);
|
2012-05-01 10:19:41 +02:00
|
|
|
protected abstract void doBind(SocketAddress localAddress, ChannelFuture future);
|
|
|
|
protected abstract void doConnect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelFuture future);
|
2012-05-02 14:05:53 +02:00
|
|
|
protected abstract void doFinishConnect(ChannelFuture future);
|
2012-05-01 10:19:41 +02:00
|
|
|
protected abstract void doDisconnect(ChannelFuture future);
|
|
|
|
protected abstract void doClose(ChannelFuture future);
|
|
|
|
protected abstract void doDeregister(ChannelFuture future);
|
|
|
|
|
|
|
|
protected abstract int doRead();
|
|
|
|
protected abstract int doFlush(ChannelFuture future);
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|