2008-08-08 02:37:18 +02:00
|
|
|
/*
|
2008-08-08 03:27:24 +02:00
|
|
|
* JBoss, Home of Professional Open Source
|
2008-08-08 02:37:18 +02:00
|
|
|
*
|
2008-08-08 03:27:24 +02:00
|
|
|
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
|
|
|
|
* by the @author tags. See the COPYRIGHT.txt in the distribution for a
|
|
|
|
* full listing of individual contributors.
|
2008-08-08 02:37:18 +02:00
|
|
|
*
|
2008-08-08 03:27:24 +02:00
|
|
|
* This 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 2.1 of
|
|
|
|
* the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This software is distributed in the hope that it will be useful,
|
2008-08-08 02:37:18 +02:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2008-08-08 03:27:24 +02:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2008-08-08 02:37:18 +02:00
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
2008-08-08 03:27:24 +02:00
|
|
|
* License along with this software; if not, write to the Free
|
|
|
|
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
|
|
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
2008-08-08 02:37:18 +02:00
|
|
|
*/
|
2008-08-08 03:40:10 +02:00
|
|
|
package org.jboss.netty.channel;
|
2008-08-08 02:37:18 +02:00
|
|
|
|
|
|
|
import java.net.SocketAddress;
|
|
|
|
import java.util.UUID;
|
|
|
|
|
2008-08-08 03:40:10 +02:00
|
|
|
import org.jboss.netty.util.TimeBasedUuidGenerator;
|
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
|
|
|
*
|
2008-08-08 03:27:24 +02:00
|
|
|
* @author The Netty Project (netty-dev@lists.jboss.org)
|
|
|
|
* @author Trustin Lee (tlee@redhat.com)
|
2008-08-08 02:37:18 +02:00
|
|
|
*
|
|
|
|
* @version $Rev$, $Date$
|
|
|
|
*
|
|
|
|
*/
|
2008-12-01 07:08:52 +01:00
|
|
|
public abstract class AbstractChannel implements Channel {
|
2008-08-08 02:37:18 +02:00
|
|
|
|
|
|
|
private final UUID id = TimeBasedUuidGenerator.generate();
|
|
|
|
private final Channel parent;
|
|
|
|
private final ChannelFactory factory;
|
|
|
|
private final ChannelPipeline pipeline;
|
|
|
|
private final ChannelFuture succeededFuture = new SucceededChannelFuture(this);
|
2008-11-26 10:21:00 +01:00
|
|
|
private final ChannelFuture closeFuture = new UnfailingChannelFuture(this, false);
|
2008-08-08 02:37:18 +02:00
|
|
|
private volatile int interestOps = OP_READ;
|
|
|
|
|
|
|
|
/** Cache for the string representation of this channel */
|
|
|
|
private String strVal;
|
|
|
|
|
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.
|
|
|
|
* @param factory
|
|
|
|
* the factory which created this channel
|
|
|
|
* @param pipeline
|
|
|
|
* the pipeline which is going to be attached to this channel
|
|
|
|
* @param sink
|
|
|
|
* the sink which will receive downstream events from the pipeline
|
|
|
|
* and send upstream events to the pipeline
|
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
protected AbstractChannel(
|
|
|
|
Channel parent, ChannelFactory factory,
|
|
|
|
ChannelPipeline pipeline, ChannelSink sink) {
|
|
|
|
|
|
|
|
this.parent = parent;
|
|
|
|
this.factory = factory;
|
|
|
|
this.pipeline = pipeline;
|
|
|
|
pipeline.attach(this, sink);
|
|
|
|
}
|
|
|
|
|
|
|
|
public final UUID getId() {
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Channel getParent() {
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFactory getFactory() {
|
|
|
|
return factory;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelPipeline getPipeline() {
|
|
|
|
return pipeline;
|
|
|
|
}
|
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
|
|
|
* Returns the cached {@link SucceededChannelFuture} instance.
|
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
protected ChannelFuture getSucceededFuture() {
|
|
|
|
return succeededFuture;
|
|
|
|
}
|
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
2008-09-24 11:48:32 +02:00
|
|
|
* Returns the {@link FailedChannelFuture} whose cause is an
|
2008-09-02 09:13:20 +02:00
|
|
|
* {@link UnsupportedOperationException}.
|
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
protected ChannelFuture getUnsupportedOperationFuture() {
|
|
|
|
return new FailedChannelFuture(this, new UnsupportedOperationException());
|
|
|
|
}
|
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
|
|
|
* Returns the {@linkplain System#identityHashCode(Object) identity hash code}
|
|
|
|
* of this channel.
|
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
@Override
|
|
|
|
public final int hashCode() {
|
|
|
|
return System.identityHashCode(this);
|
|
|
|
}
|
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
2008-09-24 11:48:32 +02:00
|
|
|
* Returns {@code true} if and only if the specified object is identical
|
|
|
|
* with this channel (i.e: {@code this == o}).
|
2008-09-02 09:13:20 +02:00
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
@Override
|
|
|
|
public final boolean equals(Object o) {
|
|
|
|
return this == o;
|
|
|
|
}
|
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
2008-09-24 11:48:32 +02:00
|
|
|
* Compares the {@linkplain #getId() ID} of the two channels.
|
2008-09-02 09:13:20 +02:00
|
|
|
*/
|
2008-08-25 10:57:03 +02:00
|
|
|
public final int compareTo(Channel o) {
|
|
|
|
return getId().compareTo(o.getId());
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isOpen() {
|
2008-11-26 10:21:00 +01:00
|
|
|
return !closeFuture.isDone();
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
|
|
|
* Marks this channel as closed. This method is intended to be called by
|
|
|
|
* an internal component - please do not call it unless you know what you
|
|
|
|
* are doing.
|
|
|
|
*
|
|
|
|
* @return {@code true} if and only if this channel was not marked as
|
|
|
|
* closed yet
|
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
protected boolean setClosed() {
|
2008-11-26 10:21:00 +01:00
|
|
|
return closeFuture.setSuccess();
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFuture bind(SocketAddress localAddress) {
|
|
|
|
return Channels.bind(this, localAddress);
|
|
|
|
}
|
|
|
|
|
2008-10-02 06:40:46 +02:00
|
|
|
public ChannelFuture unbind() {
|
|
|
|
return Channels.unbind(this);
|
|
|
|
}
|
|
|
|
|
2008-08-08 02:37:18 +02:00
|
|
|
public ChannelFuture close() {
|
2008-11-26 10:21:00 +01:00
|
|
|
ChannelFuture returnedCloseFuture = Channels.close(this);
|
|
|
|
assert closeFuture == returnedCloseFuture;
|
|
|
|
return closeFuture;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFuture getCloseFuture() {
|
|
|
|
return closeFuture;
|
2008-08-08 02:37:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFuture connect(SocketAddress remoteAddress) {
|
|
|
|
return Channels.connect(this, remoteAddress);
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFuture disconnect() {
|
|
|
|
return Channels.disconnect(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int getInterestOps() {
|
|
|
|
return interestOps;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFuture setInterestOps(int interestOps) {
|
|
|
|
return Channels.setInterestOps(this, interestOps);
|
|
|
|
}
|
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
|
|
|
* Sets the {@link #getInterestOps() interestOps} property of this channel
|
|
|
|
* immediately. This method is intended to be called by an internal
|
|
|
|
* component - please do not call it unless you know what you are doing.
|
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
protected void setInterestOpsNow(int interestOps) {
|
|
|
|
this.interestOps = interestOps;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isReadable() {
|
|
|
|
return (getInterestOps() & OP_READ) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isWritable() {
|
|
|
|
return (getInterestOps() & OP_WRITE) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFuture setReadable(boolean readable) {
|
|
|
|
if (readable) {
|
|
|
|
return setInterestOps(getInterestOps() | OP_READ);
|
|
|
|
} else {
|
|
|
|
return setInterestOps(getInterestOps() & ~OP_READ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFuture write(Object message) {
|
|
|
|
return Channels.write(this, message);
|
|
|
|
}
|
|
|
|
|
|
|
|
public ChannelFuture write(Object message, SocketAddress remoteAddress) {
|
|
|
|
return Channels.write(this, message, remoteAddress);
|
|
|
|
}
|
|
|
|
|
2008-09-02 09:13:20 +02:00
|
|
|
/**
|
|
|
|
* Returns the {@link String} representation of this channel. The returned
|
|
|
|
* string contains the {@linkplain #getId() ID}, {@linkplain #getLocalAddress() local address},
|
|
|
|
* and {@linkplain #getRemoteAddress() remote address} of this channel for
|
|
|
|
* easier identification.
|
|
|
|
*/
|
2008-08-08 02:37:18 +02:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
if (strVal != null) {
|
|
|
|
return strVal;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringBuilder buf = new StringBuilder(128);
|
|
|
|
buf.append(getClass().getSimpleName());
|
|
|
|
buf.append("(id: ");
|
|
|
|
buf.append(id.toString());
|
|
|
|
|
|
|
|
if (isConnected()) {
|
|
|
|
buf.append(", ");
|
|
|
|
if (getParent() == null) {
|
|
|
|
buf.append(getLocalAddress());
|
|
|
|
buf.append(" => ");
|
|
|
|
buf.append(getRemoteAddress());
|
|
|
|
} else {
|
|
|
|
buf.append(getRemoteAddress());
|
|
|
|
buf.append(" => ");
|
|
|
|
buf.append(getLocalAddress());
|
|
|
|
}
|
|
|
|
} else if (isBound()) {
|
|
|
|
buf.append(", ");
|
|
|
|
buf.append(getLocalAddress());
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.append(')');
|
|
|
|
|
|
|
|
return strVal = buf.toString();
|
|
|
|
}
|
|
|
|
}
|