These interfaces provide the full support for the channel programming model. The channel programming model is a virtual protocol stack layer allowing flexibility and scalability for client and server transports. By implementing the interfaces included in this package, a channel can be pulled into the framework and utilize the framework and other channels in the system.
Initial questions to answer
One should answer the following questions before designing a Channel.
- Will this implementation be a server (inbound), a client (outbound) or both?
- Which type of channel is needed? Connector, Protocol, or Application?
Terminology definitions
- Channel - A Channel is the functional equivalent of a protocol layer in a stack. A channel provides some functionality that is unique in the stack.
- Channel Chain - A Channel chain is like a protocol stack. It is a group of one or more channels linked together to perform some function.
- Inbound Channel/Chain - An Inbound Chain is a server side chain, or transport/protocol stack. Connections in this sort of chain originate at the bottom of the stack. Each channel in an Inbound Chain is an Inbound Channel. These Channels expect the connections to originate from the bottom of the stack. If this chain is connected to the network, the lowest level channel would be listening for new connections to be originated from a network client.
- Outbound Channel/Chain - An Outbound Chain is a client side chain, or transport/protocol stack. Connections in this sort of chain originate at the top of the stack. Each channel in an Outbound Chain is an Outbound Channel. These Channels expect the connections to originate from the top of the stack through a connect call. If this chain is connected to the network, the lowest level channel would be creating a new connections to a remote process. Often, there is no Application Channel in an Outbound Chain.
- Application Channel - An Application Channel is the top level channel in the protocol stack. Normally, the application channel is only necessary in the inbound side, where new connections do not originate from the application but from the lowest level channel, the connector channel. The application is looked to as the main tie from the channel chain to the application being supported. Application channels are written to explicitly understand/utilize one or more interface from a channel below.
- Connector Channel - A Connector channel is the lowest level piece. In a network Chain, this channel would facilitate all the network communication on the stack. If its not a network enabled chain, it would connect to another resource and facilitate that actual connection outside the channel chain scope. A Connector channel exposes one interface to the channels above.
- Protocol Channel - A Protocol channel is a middle channel. It is built on top of one or more interfaces and exposes 1 specific interface to channels above for them to program to. In an Outbound chain, if this is the top channel in the stack this channel's interface will be exposed through the channel API to the users of the outbound chain.
What needs implemented?
Each channel must have a couple elements in order to be plugged into a channel chain.
Inbound or Outbound implementations
- ChannelFactory - This will be instantiated by the ChannelFramework in order to create channels and to check the coherency of the chains. The coherency of the chains is checked by asking the factories for the interfaces surrounding the channel in question to ensure they are expecting one another. While multiple of them may be instantiated to check things such as chain coherency the ChannelFactory has a lifecycle of its own. Before any channel is created, the init() method will be called and the destroy method will be called once all the channels belonging to that factory have been destroyed.
- InboundChannel or OutboundChannel - The Channel is an object that can exist in multiple chains and is the primary interface in the Channel. It is created from the ChannelFactory when it is added into the Framework's configuration. The Channel has a more extensive lifecycle than the ChannelFactory with its start, stop, init, and destroy methods. It also creates the ConnectionLinks.
- InboundConnectionLink and OutboundConnectionLink - The ConnectionLink interface is the connection (represented by the VirtualConnection within the Framework) specific state and interface for the channel. There is one of these created for every VirtualConnection that this Channel will use.
Inbound implementations only
- Discriminator - This is the object the Framework will use in order to determine whether a new connection belongs to this channel or another in a channel sharing case. This case is where there are two inbound chains configured using the same connector or protocol channel. The Discriminator is responsible to look at data given by the channel below it in the stack and determine whether the connection belongs to the channel, it does not belong to the channel, or more data is needed before this determination can be made. Not all channels need to provide more data or have a way to pass more data via their interface they pass data to the channel above. If they cannot pass more data, a request for more data is viewed as a failure.
Sample Inbound flows
Here are some sample flows with pseudo code.
//MyConnectorChannel gets a new connection in.
//Creates a VirtualConnection through the ChannelFramework
VirtualConnectionFactory vcf = getChannel().getVirtualConnectionFactory();
VirtualConnection vc = vcf.createConnection();
//create a new ConnectionLink
MyConnectionLink connLink = getChannel().getConnectionLink(vc, newSocket);
//read some data
connLink.initialRead();
//fetch myChannel's discrimination process
DiscriminationProcess dp = getChannel().getDiscriminationProcess();
//track the state of the discrimination process
//set it to initially fail
int state = DiscriminationProcess.FAILURE;
while (true) {
try {
state = dp.discriminate(
getVirtualConnection(), connLink.getData(), this);
} catch (Exception e) {
// Follow the failure logic
log("DiscriminationProblem", e);
}
if (DiscriminationProcess.AGAIN == state) {
connLink.read();
continue;
}
if (DiscriminationProcess.FAILURE == state) {
// close the connection because nobody wants it
newSocket.close();
connLink.destroy();
vc.destroy();
}
break;
}
if (DiscriminationProcess.SUCCESS == state) {
getApplicationCallback().ready(getVirtualConnection());
}
}
Each channel would continue this process until the stack is created. Once the stack is created, the discrimination process will probably not occur again.